diff --git a/cs-authentication/src/main/java/com/cf/cs/authentication/interceptor/RequestBodyCacheWrapper.java b/cs-authentication/src/main/java/com/cf/cs/authentication/interceptor/RequestBodyCacheWrapper.java index 41e50c1..05b996b 100644 --- a/cs-authentication/src/main/java/com/cf/cs/authentication/interceptor/RequestBodyCacheWrapper.java +++ b/cs-authentication/src/main/java/com/cf/cs/authentication/interceptor/RequestBodyCacheWrapper.java @@ -2,6 +2,7 @@ package com.cf.cs.authentication.interceptor; import com.cf.cs.base.misc.ApiContextUtils; import com.cf.cs.base.misc.HelperUtils; +import com.cf.cs.protocol.misc.ProtocolJsonUtils; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; @@ -61,7 +62,7 @@ public class RequestBodyCacheWrapper extends HttpServletRequestWrapper { } try { - Object obj = HelperUtils.jsonGetObject(stringBuilder.toString(), Object.class); + Object obj = ProtocolJsonUtils.jsonGetObject(stringBuilder.toString(), Object.class); body = HelperUtils.getJson(obj); Enumeration enumeration = request.getHeaderNames(); diff --git a/cs-authentication/src/main/java/com/cf/cs/authentication/misc/SecurityResponseUtils.java b/cs-authentication/src/main/java/com/cf/cs/authentication/misc/SecurityResponseUtils.java index fe0db18..7ac4d79 100644 --- a/cs-authentication/src/main/java/com/cf/cs/authentication/misc/SecurityResponseUtils.java +++ b/cs-authentication/src/main/java/com/cf/cs/authentication/misc/SecurityResponseUtils.java @@ -2,8 +2,8 @@ package com.cf.cs.authentication.misc; import com.cf.cs.base.common.CommonEnumHandler; import com.cf.cs.base.common.ErrorCode; -import com.cf.cs.base.misc.HelperUtils; import com.cf.cs.database.service.OperationLogDataBaseService; +import com.cf.cs.protocol.misc.ProtocolJsonUtils; import com.cf.cs.protocol.pojo.po.BaseRespStatus; import com.cf.cs.protocol.pojo.vo.ProtocolResp; import jakarta.servlet.ServletOutputStream; @@ -41,7 +41,7 @@ public class SecurityResponseUtils { logService.securityOperationLog(request, ret, error, readme); } - outputStream.write(HelperUtils.getJsonBytes(ret)); + outputStream.write(ProtocolJsonUtils.getJsonBytes(ret)); outputStream.flush(); outputStream.close(); } @@ -69,7 +69,7 @@ public class SecurityResponseUtils { logService.securityOperationLog(request, ret, CommonEnumHandler.codeOf(ErrorCode.class, rsp.getStatus()), readme); } - outputStream.write(HelperUtils.getJsonBytes(ProtocolResp.result(rsp))); + outputStream.write(ProtocolJsonUtils.getJsonBytes(ProtocolResp.result(rsp))); outputStream.flush(); outputStream.close(); } diff --git a/cs-authentication/src/main/java/com/cf/cs/authentication/security/impl/JwtCustomUsernamePassword.java b/cs-authentication/src/main/java/com/cf/cs/authentication/security/impl/JwtCustomUsernamePassword.java index 0276469..356dcf3 100644 --- a/cs-authentication/src/main/java/com/cf/cs/authentication/security/impl/JwtCustomUsernamePassword.java +++ b/cs-authentication/src/main/java/com/cf/cs/authentication/security/impl/JwtCustomUsernamePassword.java @@ -12,6 +12,7 @@ import com.cf.cs.base.misc.HelperUtils; import com.cf.cs.base.pojo.po.JwtCache; import com.cf.cs.database.service.OperationLogDataBaseService; import com.cf.cs.protocol.config.ProtocolConfigure; +import com.cf.cs.protocol.misc.ProtocolJsonUtils; import com.cf.cs.protocol.pojo.dto.LoginReq; import com.cf.cs.protocol.pojo.dto.ProtocolReq; import com.cf.cs.protocol.pojo.po.BaseRespStatus; @@ -71,8 +72,8 @@ public class JwtCustomUsernamePassword extends UsernamePasswordAuthenticationFil } try { - ProtocolReq loginReq = HelperUtils.jsonGetObject(request.getInputStream(), - new TypeReference<>() { + ProtocolReq loginReq = ProtocolJsonUtils.jsonGetObject(request.getInputStream(), + new TypeReference<>() { }); List validate = HelperUtils.validate(loginReq, ValidGroups.ProtocolCommonValid.class, ValidGroups.LogoutReqValid.class); diff --git a/cs-base/src/main/java/com/cf/cs/base/misc/HelperUtils.java b/cs-base/src/main/java/com/cf/cs/base/misc/HelperUtils.java index cea9c12..ed2b447 100644 --- a/cs-base/src/main/java/com/cf/cs/base/misc/HelperUtils.java +++ b/cs-base/src/main/java/com/cf/cs/base/misc/HelperUtils.java @@ -4,9 +4,7 @@ package com.cf.cs.base.misc; import com.cf.cs.base.common.ConstValue; import com.cf.cs.base.config.ObjectMapperProvider; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validation; @@ -20,7 +18,6 @@ import java.io.Reader; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.sql.Timestamp; import java.time.LocalDateTime; @@ -40,6 +37,18 @@ import java.util.Set; public class HelperUtils { private static final ObjectMapper OBJ_MAPPER = ObjectMapperProvider.getMapper(); + /** + * Gets json. + * + * @param the type parameter + * @param obj the obj + * @return the json + * @throws JsonProcessingException the json processing exception + */ + public static String getJson(T obj) throws JsonProcessingException { + return OBJ_MAPPER.writeValueAsString(obj); + } + /** * Truncate string string. * @@ -132,82 +141,6 @@ public class HelperUtils { return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } - /** - * Gets json. - * - * @param the type parameter - * @param obj the obj - * @return the json - * @throws JsonProcessingException the json processing exception - */ - public static String getJson(T obj) throws JsonProcessingException { - return OBJ_MAPPER.writeValueAsString(obj); - } - - /** - * Get json bytes byte [ ]. - * - * @param the type parameter - * @param obj the obj - * @param charset the charset - * @return the byte [ ] - * @throws JsonProcessingException the json processing exception - */ - public static byte[] getJsonBytes(T obj, Charset charset) throws JsonProcessingException { - return OBJ_MAPPER.writeValueAsString(obj).getBytes(charset); - } - - /** - * Get json bytes byte [ ]. - * - * @param the type parameter - * @param obj the obj - * @return the byte [ ] - * @throws JsonProcessingException the json processing exception - */ - public static byte[] getJsonBytes(T obj) throws JsonProcessingException { - return OBJ_MAPPER.writeValueAsString(obj).getBytes(StandardCharsets.UTF_8); - } - - /** - * Json get object object. - * - * @param the type parameter - * @param json the json - * @param valueType the value type - * @return the object - * @throws JsonProcessingException the json processing exception - */ - public static Object jsonGetObject(String json, Class valueType) throws JsonProcessingException { - return OBJ_MAPPER.readValue(json, valueType); - } - - /** - * Json get object t. - * - * @param the type parameter - * @param is the is - * @param valueTypeRef the value type ref - * @return the t - * @throws IOException the io exception - */ - public static T jsonGetObject(ServletInputStream is, TypeReference valueTypeRef) throws IOException { - return OBJ_MAPPER.readValue(inputStream2String(is), valueTypeRef); - } - - /** - * Json get object t. - * - * @param the type parameter - * @param json the json - * @param valueTypeRef the value type ref - * @return the t - * @throws IOException the io exception - */ - public static T jsonGetObject(String json, TypeReference valueTypeRef) throws IOException { - return OBJ_MAPPER.readValue(json, valueTypeRef); - } - /** * Validate list. * diff --git a/cs-integrate-test/pom.xml b/cs-integrate-test/pom.xml new file mode 100644 index 0000000..a339588 --- /dev/null +++ b/cs-integrate-test/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + com.cf.cs + IntegrateService + 0.0.1-dev + + + cs-integrate-test + cs-integrate-test + cs-integrate-test + jar + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.junit.platform + junit-platform-suite-engine + 1.10.2 + test + + + org.jacoco + jacoco-maven-plugin + 0.8.11 + + + + com.cf.cs + cs-restful + ${cs-package.version} + compile + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + false + + **/*.java + + + + + org.jacoco + jacoco-maven-plugin + 0.8.11 + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + + + diff --git a/cs-integrate-test/src/main/java/com/cf/cs/integratetest/CsIntegrateTestApplication.java b/cs-integrate-test/src/main/java/com/cf/cs/integratetest/CsIntegrateTestApplication.java new file mode 100644 index 0000000..207144d --- /dev/null +++ b/cs-integrate-test/src/main/java/com/cf/cs/integratetest/CsIntegrateTestApplication.java @@ -0,0 +1,13 @@ +package com.cf.cs.integratetest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CsIntegrateTestApplication { + + public static void main(String[] args) { + SpringApplication.run(CsIntegrateTestApplication.class, args); + } + +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/IntegrationTestSuite.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/IntegrationTestSuite.java new file mode 100644 index 0000000..854954f --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/IntegrationTestSuite.java @@ -0,0 +1,16 @@ +package com.cf.cs.integratetest; + +import com.cf.cs.integratetest.controller.CommonFrameworkApiTest; +import com.cf.cs.integratetest.controller.OperationLogApiTest; +import com.cf.cs.integratetest.controller.PermissionManagerApiTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; + +@SelectClasses({CommonFrameworkApiTest.class, + OperationLogApiTest.class, + PermissionManagerApiTest.class}) +@DisplayName("接口集成测试") +@Suite +public class IntegrationTestSuite { +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/common/TestBaseAuthentication.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/common/TestBaseAuthentication.java new file mode 100644 index 0000000..611555c --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/common/TestBaseAuthentication.java @@ -0,0 +1,171 @@ +package com.cf.cs.integratetest.common; + + +import com.cf.cs.base.common.ConstValue; +import com.cf.cs.base.common.ErrorCode; +import com.cf.cs.base.common.ProtoCryptoType; +import com.cf.cs.base.misc.HelperUtils; +import com.cf.cs.protocol.config.ProtocolConfigure; +import com.cf.cs.protocol.pojo.dto.LoginReq; +import com.cf.cs.protocol.pojo.dto.ProtocolReq; +import com.cf.cs.protocol.pojo.po.BaseRespStatus; +import com.cf.cs.protocol.pojo.vo.LoginResp; +import com.cf.cs.protocol.pojo.vo.ProtocolResp; +import com.cf.cs.protocol.service.ProtocolSecurityService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.Objects; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@AutoConfigureMockMvc +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class TestBaseAuthentication { + protected static final ThreadLocal headersThreadLocal = new ThreadLocal<>(); + + @Autowired + protected MockMvc mockMvc; + + @Resource + private ProtocolSecurityService securityService; + + public HttpHeaders getHeaders() { + return headersThreadLocal.get(); + } + + @BeforeAll + public void setUpClass() throws Exception { + LoginReq logReq = LoginReq.builder() + .username("admin") + .password("8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918") + .build(); + + ProtocolReq loginPro = new ProtocolReq<>(); + loginPro.setMsgContent(logReq); + loginPro.setVer(1); + loginPro.setTimeStamp(System.currentTimeMillis()); + loginPro.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + + MvcResult mvcResult = mockMvc.perform(post("/api/login") + .contentType(MediaType.APPLICATION_JSON) // Set the content type to JSON + .content(HelperUtils.getJson(loginPro))) // Pass the JSON request body + .andExpect(status().isOk()) // Expect that the status is 200 OK + .andReturn(); + + // 假设JWT在响应体中返回。您需要根据实际情况调整此行代码。 + String respJson = mvcResult.getResponse().getContentAsString(); + Assertions.assertNotNull(respJson); + Assertions.assertNotEquals(respJson.length(), 0); + ProtocolResp resp = HelperUtils.jsonGetProtocolResp(respJson, LoginResp.class); + + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getMsgContent()); + Assertions.assertEquals(resp.getCode(), HttpStatus.OK.value()); + + LoginResp loginResp = (LoginResp) resp.getMsgContent(); + + Assertions.assertEquals(loginResp.getStatus(), ErrorCode.ERR_OK.getCode()); + Assertions.assertNotNull(loginResp.getToken()); + Assertions.assertNotEquals(loginResp.getToken().length(), 0); + + HttpHeaders headers = new HttpHeaders(); + MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); + headers.setContentType(type); + headers.add("Accept", MediaType.APPLICATION_JSON.toString()); + headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br"); + headers.setBearerAuth(loginResp.getToken()); + headersThreadLocal.set(headers); + } + + public Object performanceRestful(RequestMethod reqType, T reqObject, String urlPath, Class[] subRespClass) throws Exception { + MockHttpServletRequestBuilder build = createMockMvcBuilder(urlPath, reqType); + + if (Objects.nonNull(reqObject)) { + String sendMsgContent; + ProtocolReq reqInfo = new ProtocolReq<>(); + reqInfo.setVer(ConstValue.Protocol.VERSION); + reqInfo.setCryptoType(ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + reqInfo.setTimeStamp(System.currentTimeMillis()); + reqInfo.setMsgContent(reqObject); + + if (ProtocolConfigure.SECURITY_PROTOCOL_TYPE != ProtoCryptoType.CRYPTO_NONE.getValue()) { + String cipherText = securityService.encryptProtocolString(HelperUtils.getJson(reqObject), + ProtocolConfigure.SECURITY_PROTOCOL_TYPE); + + ProtocolReq cipherInfo = new ProtocolReq<>(); + cipherInfo.setVer(reqInfo.getVer()); + cipherInfo.setCryptoType(reqInfo.getCryptoType()); + cipherInfo.setTimeStamp(System.currentTimeMillis()); + cipherInfo.setMsgContent(cipherText); + sendMsgContent = HelperUtils.getJson(cipherInfo); + } else { + sendMsgContent = HelperUtils.getJson(reqInfo); + } + + build.content(sendMsgContent); + } + + + String rspValue = mockMvc.perform(build) + .andDo(print()) + .andReturn() + .getResponse() + .getContentAsString(); + + AssertValidString(rspValue); + + rspValue = securityService.decryptProtocol(rspValue); + AssertValidString(rspValue); + + ProtocolResp resp = HelperUtils.jsonGetProtocolResp(rspValue, subRespClass); + + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getMsgContent()); + Assertions.assertEquals(resp.getCode(), HttpStatus.OK.value()); + + return resp.getMsgContent(); + } + + private MockHttpServletRequestBuilder createMockMvcBuilder(String uri, RequestMethod reqType) { + MockHttpServletRequestBuilder build = switch (reqType) { + case PUT -> MockMvcRequestBuilders.put(uri); + case GET -> MockMvcRequestBuilders.get(uri); + case DELETE -> MockMvcRequestBuilders.delete(uri); + default -> MockMvcRequestBuilders.post(uri); + }; + + build.accept(MediaType.APPLICATION_JSON); + build.headers(getHeaders()); + return build; + } + + public void AssertValidString(String str) { + Assertions.assertNotNull(str); + Assertions.assertFalse(str.isEmpty()); + } + + public void AssertValidCommonResp(T resp) { + Assertions.assertNotNull(resp); + Assertions.assertNotNull(resp.getStatus()); + Assertions.assertNotNull(resp.getMessage()); + Assertions.assertNotEquals(resp.getMessage().length, 0); + Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode()); + } +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/CommonFrameworkApiTest.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/CommonFrameworkApiTest.java new file mode 100644 index 0000000..c0126f4 --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/CommonFrameworkApiTest.java @@ -0,0 +1,47 @@ +package com.cf.cs.integratetest.controller; + +import com.cmhi.cf.common.TestBaseAuthentication; +import com.cmhi.cf.restapi.pojo.vo.VersionResp; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMethod; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +public class CommonFrameworkApiTest extends TestBaseAuthentication { + @Test + @DisplayName("获取版本信息") + void testGetVersion() throws Exception { + VersionResp resp = (VersionResp) performanceRestful(RequestMethod.GET, null, "/api/version", new Class[]{VersionResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getVersion()); + + Assertions.assertNotNull(resp.getVersion().getTagName()); + AssertValidString(resp.getVersion().getCommitId()); + AssertValidString(resp.getVersion().getCommitDescribe()); + AssertValidString(resp.getVersion().getCommitTime()); + AssertValidString(resp.getVersion().getBuildTime()); + AssertValidString(resp.getVersion().getGitBranch()); + } + + @Test + @DisplayName("获取版本信息(POST)") + void testGetVersionV2() throws Exception { + VersionResp resp = (VersionResp) performanceRestful(RequestMethod.POST, null, "/api/version", new Class[]{VersionResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getVersion()); + + Assertions.assertNotNull(resp.getVersion().getTagName()); + AssertValidString(resp.getVersion().getCommitId()); + AssertValidString(resp.getVersion().getCommitDescribe()); + AssertValidString(resp.getVersion().getCommitTime()); + AssertValidString(resp.getVersion().getBuildTime()); + AssertValidString(resp.getVersion().getGitBranch()); + } +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/OperationLogApiTest.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/OperationLogApiTest.java new file mode 100644 index 0000000..9e4153d --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/OperationLogApiTest.java @@ -0,0 +1,107 @@ +package com.cf.cs.integratetest.controller; + +import com.cmhi.cf.common.ErrorCode; +import com.cmhi.cf.common.TestBaseAuthentication; +import com.cmhi.cf.restapi.pojo.base.BasePageResultResp; +import com.cmhi.cf.restapi.pojo.dto.OperationLogDetailsReq; +import com.cmhi.cf.restapi.pojo.dto.OperationLogReq; +import com.cmhi.cf.restapi.pojo.po.OperationLogSummary; +import com.cmhi.cf.restapi.pojo.vo.OperationLogDetailsResp; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.ArrayList; +import java.util.List; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class OperationLogApiTest extends TestBaseAuthentication { + private final List optIdArray = new ArrayList<>(); + + @Test + @Order(1) + @DisplayName("获取操作日志摘要(分页)") + void testGetSummary() throws Exception { + final long pageSize = 10L; + final long pageNumber = 1L; + + OperationLogReq req = new OperationLogReq(); + req.setPageNumber(pageNumber); + req.setPageSize(pageSize); + req.setTotalSize(-1L); + + Object obj = performanceRestful(RequestMethod.POST, req, "/api/operation/summary", + new Class[] {BasePageResultResp.class, OperationLogSummary.class}); + Assertions.assertNotNull(obj); + BasePageResultResp resp = (BasePageResultResp) obj; + AssertValidCommonResp(resp); + + Assertions.assertNotNull(resp.getItems()); + Assertions.assertFalse(resp.getItems().getItems().isEmpty()); + Assertions.assertEquals(resp.getItems().getPageSize(), pageSize); + Assertions.assertEquals(resp.getItems().getPageNumber(), pageNumber); + Assertions.assertTrue(resp.getItems().getTotalPage() > 0); + Assertions.assertTrue(resp.getItems().getTotalRow() > 0); + + List items = resp.getItems().getItems(); + + for (Object o : items) { + Assertions.assertNotNull(o); + } + + resp.getItems().getItems().forEach(k -> { + Assertions.assertInstanceOf(OperationLogSummary.class, k); + OperationLogSummary o = (OperationLogSummary) k; + Assertions.assertNotNull(o); + Assertions.assertNotNull(o.getId()); + Assertions.assertNotNull(o.getOperationTime()); + AssertValidString(o.getModule()); + AssertValidString(o.getOperationType()); + AssertValidString(o.getOperationStatus()); + AssertValidString(o.getDescription()); + AssertValidString(o.getRequestIp()); + AssertValidString(o.getHttpMethod()); + AssertValidString(o.getHttpPath()); + + optIdArray.add(o.getId()); + }); + } + + @Test + @Order(2) + @DisplayName("获取操作日志详情") + void testGetDetails() throws Exception { + Assertions.assertFalse(optIdArray.isEmpty()); + + OperationLogDetailsReq req = new OperationLogDetailsReq(optIdArray); + + Object obj = performanceRestful(RequestMethod.POST, req, "/api/operation/details", + new Class[] {OperationLogDetailsResp.class}); + Assertions.assertNotNull(obj); + OperationLogDetailsResp resp = (OperationLogDetailsResp) obj; + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getOperationLog()); + Assertions.assertFalse(resp.getOperationLog().isEmpty()); + + resp.getOperationLog().forEach(k -> { + Assertions.assertEquals(k.getStatus(), ErrorCode.ERR_OK.getCode()); + AssertValidString(k.getRequest()); + AssertValidString(k.getResult()); + AssertValidString(k.getRequestHeaders()); + Assertions.assertNotNull(k.getId()); + }); + } +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/PermissionManagerApiTest.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/PermissionManagerApiTest.java new file mode 100644 index 0000000..d85608c --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/PermissionManagerApiTest.java @@ -0,0 +1,224 @@ +package com.cf.cs.integratetest.controller; + +import com.cmhi.cf.authentication.pojo.dto.IdArrayReq; +import com.cmhi.cf.authentication.pojo.dto.RegisterResourceReq; +import com.cmhi.cf.authentication.pojo.dto.UserIdReq; +import com.cmhi.cf.authentication.pojo.po.ResourceInfo; +import com.cmhi.cf.authentication.pojo.vo.GetRoleResp; +import com.cmhi.cf.authentication.pojo.vo.RegisterResourceResp; +import com.cmhi.cf.authentication.pojo.vo.UserResPermInfoResp; +import com.cmhi.cf.common.ErrorCode; +import com.cmhi.cf.common.TestBaseAuthentication; +import com.cmhi.cf.database.authentication.entity.User; +import com.cmhi.cf.database.authentication.service.UserService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class PermissionManagerApiTest extends TestBaseAuthentication { + private final List addResUid = new ArrayList<>(); + + @Autowired + private UserService userService; + + @Test + @DisplayName("获取当前用户资源信息") + void testGetCurrentUserResourcePermission() throws Exception { + UserResPermInfoResp resp = (UserResPermInfoResp) performanceRestful(RequestMethod.GET, null, "/api/permission/resourcePermission", + new Class[] {UserResPermInfoResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResPermission()); + AssertValidString(resp.getUserId()); + AssertValidString(resp.getUsername()); + + Assertions.assertFalse(resp.getResPermission().isEmpty()); + + resp.getResPermission().forEach(k -> { + Assertions.assertNotNull(k.getId()); + AssertValidString(k.getHttpMethod()); + AssertValidString(k.getPath()); + AssertValidString(k.getName()); + Assertions.assertNotNull(k.getResTypeId()); + Assertions.assertNotNull(k.getEnable()); + }); + } + + @Test + @DisplayName("获取用户资源信息") + void testGetUserResourcePermission() throws Exception { + User user = userService.getAccountUserByName("admin"); + Assertions.assertNotNull(user); + AssertValidString(user.getUid()); + UserResPermInfoResp resp = (UserResPermInfoResp) performanceRestful(RequestMethod.POST, new UserIdReq(user.getUid()), + "/api/permission/resourcePermission", + new Class[] {UserResPermInfoResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResPermission()); + AssertValidString(resp.getUserId()); + AssertValidString(resp.getUsername()); + + Assertions.assertFalse(resp.getResPermission().isEmpty()); + + resp.getResPermission().forEach(k -> { + Assertions.assertNotNull(k.getId()); + AssertValidString(k.getHttpMethod()); + AssertValidString(k.getPath()); + AssertValidString(k.getName()); + Assertions.assertNotNull(k.getResTypeId()); + Assertions.assertNotNull(k.getEnable()); + }); + } + + @Test + @DisplayName("不存在的用户获取资源信息") + void testGetUserResourcePermission_UserServiceGetAccountUserByUidReturnsNull() { + User user = userService.getAccountUserByUid("ff99fd68-14bf-4fd6-9320-bab85839245c"); + Assertions.assertNull(user); + } + + @Test + @DisplayName("获取用户资源信息, 当前用户无资源") + void testGetUserResourcePermission_UserServiceGetUserResourcePermReturnsNoItems() throws Exception { + User user = userService.getAccountUserByName("guest"); + Assertions.assertNotNull(user); + AssertValidString(user.getUid()); + UserResPermInfoResp resp = (UserResPermInfoResp) performanceRestful(RequestMethod.POST, new UserIdReq(user.getUid()), + "/api/permission/resourcePermission", + new Class[] {UserResPermInfoResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResPermission()); + AssertValidString(resp.getUserId()); + AssertValidString(resp.getUsername()); + + Assertions.assertFalse(resp.getResPermission().isEmpty()); + + resp.getResPermission().forEach(k -> { + Assertions.assertNotNull(k.getId()); + AssertValidString(k.getHttpMethod()); + AssertValidString(k.getPath()); + AssertValidString(k.getName()); + Assertions.assertNotNull(k.getResTypeId()); + Assertions.assertNotNull(k.getEnable()); + Assertions.assertFalse(k.getEnable()); + }); + } + + @Test + @DisplayName("获取当前所有用户组") + void testGetAllRoles() throws Exception { + GetRoleResp resp = (GetRoleResp) performanceRestful(RequestMethod.GET, null, "/api/permission/allRoles", + new Class[] {GetRoleResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getRoles()); + Assertions.assertFalse(resp.getRoles().isEmpty()); + resp.getRoles().forEach(k -> { + Assertions.assertNotNull(k.getId()); + AssertValidString(k.getDescription()); + Assertions.assertNotNull(k.getName()); + Assertions.assertNotNull(k.getAvailable()); + }); + } + + @Test + @DisplayName("删除不存在的资源") + void testRemoveResourceById_UserServiceReturnsNoItems() throws Exception { + List rid = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + rid.add(UUID.randomUUID().toString()); + } + + IdArrayReq req = new IdArrayReq(rid); + + RegisterResourceResp resp = (RegisterResourceResp) performanceRestful(RequestMethod.DELETE, req, + "/api/permission/resource", + new Class[] {RegisterResourceResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResult()); + Assertions.assertEquals(resp.getResult().size(), rid.size()); + + resp.getResult().forEach(k -> { + Assertions.assertEquals(k.getStatus(), ErrorCode.ERR_NOSUCHITEM.getCode()); + Assertions.assertNotNull(k.getRid()); + }); + } + + @Test + @DisplayName("注册新资源") + void testRegisterResource() throws Exception { + addResUid.clear(); + List resList = new ArrayList<>(); + resList.add(ResourceInfo.builder() + .path("/api/custom/show") + .name("show") + .resTypeId(0) + .httpMethod(new ArrayList<>() {{add("POST");}}) + .build()); + + resList.add(ResourceInfo.builder() + .path("/api/custom/List") + .name("List") + .resTypeId(1) + .httpMethod(new ArrayList<>() {{add("PUT");}}) + .build()); + + RegisterResourceReq req = RegisterResourceReq.builder() + .resources(resList) + .build(); + + RegisterResourceResp resp = (RegisterResourceResp) performanceRestful(RequestMethod.PUT, req, + "/api/permission/resource", + new Class[] {RegisterResourceResp.class}); + + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResult()); + Assertions.assertEquals(resp.getResult().size(), resList.size()); + + resp.getResult().forEach(k -> { + AssertValidCommonResp(k); + AssertValidString(k.getRid()); + AssertValidString(k.getPath()); + AssertValidString(k.getHttpMethod()); + Assertions.assertNotNull(k.getResTypeId()); + addResUid.add(k.getRid()); + }); + } + + @Test + @DisplayName("删除资源") + void testRemoveResourceById() throws Exception { + testRegisterResource(); + IdArrayReq req = new IdArrayReq(addResUid); + + RegisterResourceResp resp = (RegisterResourceResp) performanceRestful(RequestMethod.DELETE, req, + "/api/permission/resource", + new Class[] {RegisterResourceResp.class}); + AssertValidCommonResp(resp); + Assertions.assertNotNull(resp.getResult()); + Assertions.assertEquals(resp.getResult().size(), addResUid.size()); + + resp.getResult().forEach(k -> { + AssertValidCommonResp(k); + AssertValidString(k.getRid()); + Assertions.assertTrue(addResUid.contains(k.getRid())); + }); + } +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/SystemDictControllerTest.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/SystemDictControllerTest.java new file mode 100644 index 0000000..f9fec73 --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/SystemDictControllerTest.java @@ -0,0 +1,38 @@ +package com.cf.cs.integratetest.controller; + +import com.cmhi.cf.common.TestBaseAuthentication; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +public class SystemDictControllerTest extends TestBaseAuthentication { + @Test + void testGetEnumDictionary() throws Exception { + + } + + @Test + void testGetEnumDictionary_DictionaryServiceReturnsNoItems() throws Exception { + + } + + @Test + void testGetEnumDictionaryContent() throws Exception { + + } + + @Test + void testGetEnumDictionaryContent_DictionaryServiceReturnsNoItems() throws Exception { + + } + + @Test + void testCreateNewDictionary() throws Exception { + + } +} diff --git a/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/UserManagerApiTest.java b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/UserManagerApiTest.java new file mode 100644 index 0000000..d47e816 --- /dev/null +++ b/cs-integrate-test/src/test/java/com/cf/cs/integratetest/controller/UserManagerApiTest.java @@ -0,0 +1,43 @@ +package com.cf.cs.integratetest.controller; + +import com.cmhi.cf.common.TestBaseAuthentication; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; + +@ExtendWith({SpringExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class UserManagerApiTest extends TestBaseAuthentication { + @Test + void testGetUserInfoById() throws Exception { + + } + + @Test + void testGetAllUserInfoPaged() throws Exception { + + } + + @Test + void testGetCurrentUserInfo() throws Exception { + + } + + @Test + void testCreateNewUser() throws Exception { + + } + + @Test + void testRemoveUser() throws Exception { + + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/misc/JsonParameterizedType.java b/cs-protocol/src/main/java/com/cf/cs/protocol/misc/JsonParameterizedType.java new file mode 100644 index 0000000..c2f6fe6 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/misc/JsonParameterizedType.java @@ -0,0 +1,119 @@ +package com.cf.cs.protocol.misc; + +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.Objects; + +/** + * The type Json parameterized type. + * + * @author xajhuang @163.com + */ +public class JsonParameterizedType implements ParameterizedType { + private final Type[] actualTypeArguments; + private final Class rawType; + private final Type ownerType; + + private JsonParameterizedType(Class var1, Type[] var2, Type var3) { + this.actualTypeArguments = var2; + this.rawType = var1; + this.ownerType = (var3 != null ? var3 : var1.getDeclaringClass()); + this.validateConstructorArguments(); + } + + private void validateConstructorArguments() { + TypeVariable[] var1 = this.rawType.getTypeParameters(); + if (var1.length != this.actualTypeArguments.length) { + throw new MalformedParameterizedTypeException(); + } + } + + @Override + public Type[] getActualTypeArguments() { + return this.actualTypeArguments.clone(); + } + + @Override + public Type getRawType() { + return this.rawType; + } + + @Override + public Type getOwnerType() { + return this.ownerType; + } + + @Override + public boolean equals(Object var1) { + if (var1 instanceof ParameterizedType var2) { + if (this == var2) { + return true; + } else { + Type var3 = var2.getOwnerType(); + Type var4 = var2.getRawType(); + return Objects.equals(this.ownerType, var3) && Objects.equals(this.rawType, var4) && Arrays.equals(this.actualTypeArguments, var2.getActualTypeArguments()); + } + } else { + return false; + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(this.actualTypeArguments) ^ Objects.hashCode(this.ownerType) ^ Objects.hashCode(this.rawType); + } + + @Override + public String toString() { + StringBuilder var1 = new StringBuilder(); + if (this.ownerType != null) { + if (this.ownerType instanceof Class) { + var1.append(((Class)this.ownerType).getName()); + } else { + var1.append(this.ownerType); + } + + var1.append("$"); + if (this.ownerType instanceof JsonParameterizedType) { + var1.append(this.rawType.getName().replace(((JsonParameterizedType)this.ownerType).rawType.getName() + "$", "")); + } else { + var1.append(this.rawType.getSimpleName()); + } + } else { + var1.append(this.rawType.getName()); + } + + if (this.actualTypeArguments != null && this.actualTypeArguments.length > 0) { + var1.append("<"); + boolean var2 = true; + + for (Type var6 : this.actualTypeArguments) { + if (!var2) { + var1.append(", "); + } + + var1.append(var6.getTypeName()); + var2 = false; + } + + var1.append(">"); + } + + return var1.toString(); + } + + /** + * Make json parameterized type. + * + * @param var0 the var 0 + * @param var1 the var 1 + * @param var2 the var 2 + * @return the json parameterized type + */ + public static JsonParameterizedType make(Class var0, Type[] var1, Type var2) { + return new JsonParameterizedType(var0, var1, var2); + } +} diff --git a/cs-protocol/src/main/java/com/cf/cs/protocol/misc/ProtocolJsonUtils.java b/cs-protocol/src/main/java/com/cf/cs/protocol/misc/ProtocolJsonUtils.java new file mode 100644 index 0000000..aec6832 --- /dev/null +++ b/cs-protocol/src/main/java/com/cf/cs/protocol/misc/ProtocolJsonUtils.java @@ -0,0 +1,179 @@ +package com.cf.cs.protocol.misc; + +import com.cf.cs.base.config.ObjectMapperProvider; +import com.cf.cs.base.misc.HelperUtils; +import com.cf.cs.protocol.pojo.po.BaseRespStatus; +import com.cf.cs.protocol.pojo.vo.ProtocolResp; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.ServletInputStream; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Stack; + +/** + * The type Protocol json utils. + * + * @author xajhuang @163.com + */ +public class ProtocolJsonUtils { + private static final ObjectMapper OBJ_MAPPER = ObjectMapperProvider.getMapper(); + + /** + * Get json bytes byte [ ]. + * + * @param the type parameter + * @param obj the obj + * @param charset the charset + * @return the byte [ ] + * @throws JsonProcessingException the json processing exception + */ + public static byte[] getJsonBytes(T obj, Charset charset) throws JsonProcessingException { + return OBJ_MAPPER.writeValueAsString(obj).getBytes(charset); + } + + /** + * Get json bytes byte [ ]. + * + * @param the type parameter + * @param obj the obj + * @return the byte [ ] + * @throws JsonProcessingException the json processing exception + */ + public static byte[] getJsonBytes(T obj) throws JsonProcessingException { + return OBJ_MAPPER.writeValueAsString(obj).getBytes(StandardCharsets.UTF_8); + } + + /** + * Json get object object. + * + * @param the type parameter + * @param json the json + * @param valueType the value type + * @return the object + * @throws JsonProcessingException the json processing exception + */ + public static Object jsonGetObject(String json, Class valueType) throws JsonProcessingException { + return OBJ_MAPPER.readValue(json, valueType); + } + + /** + * Json get object t. + * + * @param the type parameter + * @param is the is + * @param valueTypeRef the value type ref + * @return the t + * @throws IOException the io exception + */ + public static T jsonGetObject(ServletInputStream is, TypeReference valueTypeRef) throws IOException { + return OBJ_MAPPER.readValue(HelperUtils.inputStream2String(is), valueTypeRef); + } + + /** + * Json get object t. + * + * @param the type parameter + * @param json the json + * @param valueTypeRef the value type ref + * @return the t + * @throws IOException the io exception + */ + public static T jsonGetObject(String json, TypeReference valueTypeRef) throws IOException { + return OBJ_MAPPER.readValue(json, valueTypeRef); + } + + private static Type createRespType(Class c) { + return new ParameterizedType() { + @Override + public Type[] getActualTypeArguments() { + // 返回实际类型参数,例如List的String + return new Type[] {c}; + } + + @Override + public Type getRawType() { + // 返回原始类型,例如List + return ProtocolResp.class; + } + + @Override + public Type getOwnerType() { + // 返回类型所在的类,对于顶级类是null + return null; + } + }; + } + + /** + * Json get protocol resp protocol resp. + * + * @param the type parameter + * @param jsonString the json string + * @param subClass the sub class + * @return the protocol resp + * @throws JsonProcessingException the json processing exception + */ + public static ProtocolResp jsonGetProtocolResp(String jsonString, + Class subClass) throws JsonProcessingException { + return OBJ_MAPPER.readValue(jsonString, new TypeReference<>() { + @Override + public Type getType() { + return createRespType(subClass); + } + }); + } + + private static Type createRespType(Class[] c) { + if (c.length == 1) { + return createRespType(c[0]); + } + + Stack> st = new Stack<>(); + + Arrays.stream(c).forEach(st::push); + + Class fc = st.pop(); + Class sc = st.pop(); + JsonParameterizedType type = JsonParameterizedType.make(sc, + new Type[] {fc}, + sc.getDeclaringClass()); + + while (!st.isEmpty()) { + Class mc = st.pop(); + type = JsonParameterizedType.make(mc, + new Type[] {type}, + mc.getDeclaringClass()); + } + + type = JsonParameterizedType.make(ProtocolResp.class, + new Type[] {type}, + ProtocolResp.class.getDeclaringClass()); + + return type; + } + + /** + * Json get protocol resp protocol resp. + * + * @param jsonString the json string + * @param subClass the sub class + * @return the protocol resp + * @throws JsonProcessingException the json processing exception + */ + public static ProtocolResp jsonGetProtocolResp(String jsonString, + Class[] subClass) throws JsonProcessingException { + return OBJ_MAPPER.readValue(jsonString, new TypeReference<>() { + @Override + public Type getType() { + return createRespType(subClass); + } + }); + } +} diff --git a/pom.xml b/pom.xml index 1738082..bb9c9ba 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ cs-database cs-authentication cs-restful + cs-integrate-test