diff --git a/pom.xml b/pom.xml
index f35f0cf..59dee0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,12 @@
spring-security-test
test
+
+ org.junit.platform
+ junit-platform-suite-engine
+ 1.10.2
+ test
+
org.springframework.boot
spring-boot-starter-undertow
diff --git a/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java b/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java
index 69fce74..e9f5ebf 100644
--- a/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java
+++ b/src/main/java/com/cmhi/cf/controller/CommonFrameworkApi.java
@@ -5,6 +5,7 @@ import com.cmhi.cf.restapi.annotation.DecryptionProtocol;
import com.cmhi.cf.restapi.annotation.EncryptionProtocol;
import com.cmhi.cf.restapi.annotation.OperationLogAnnotation;
import com.cmhi.cf.restapi.pojo.base.BaseRespStatus;
+import com.cmhi.cf.restapi.pojo.po.VersionInfo;
import com.cmhi.cf.restapi.pojo.vo.ProtocolResp;
import com.cmhi.cf.restapi.pojo.vo.VersionResp;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -31,7 +32,14 @@ public class CommonFrameworkApi {
@OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息")
public ProtocolResp extends BaseRespStatus> getVersion() {
return ProtocolResp.result(VersionResp.builder()
- .version(prgVer)
+ .version(VersionInfo.builder()
+ .commitId(prgVer.getCommitId())
+ .commitDescribe(prgVer.getCommitDescribe())
+ .commitTime(prgVer.getCommitTime())
+ .tagName(prgVer.getTagName())
+ .buildTime(prgVer.getBuildTime())
+ .gitBranch(prgVer.getGitBranch())
+ .build())
.build());
}
@@ -41,7 +49,14 @@ public class CommonFrameworkApi {
@OperationLogAnnotation(OperationModule = "通用模块", OperationType = "读取", OperationDesc = "获取当前系统版本信息")
public ProtocolResp extends BaseRespStatus> getVersionV2() {
return ProtocolResp.result(VersionResp.builder()
- .version(prgVer)
+ .version(VersionInfo.builder()
+ .commitId(prgVer.getCommitId())
+ .commitDescribe(prgVer.getCommitDescribe())
+ .commitTime(prgVer.getCommitTime())
+ .tagName(prgVer.getTagName())
+ .buildTime(prgVer.getBuildTime())
+ .gitBranch(prgVer.getGitBranch())
+ .build())
.build());
}
}
diff --git a/src/main/java/com/cmhi/cf/misc/HelperUtils.java b/src/main/java/com/cmhi/cf/misc/HelperUtils.java
index a8ae1ce..f9418ef 100644
--- a/src/main/java/com/cmhi/cf/misc/HelperUtils.java
+++ b/src/main/java/com/cmhi/cf/misc/HelperUtils.java
@@ -28,11 +28,13 @@ import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Stack;
public class HelperUtils {
public static final String UN_EXPECT_REGEX_CHARS = "^((?!(--|\\s|\\*|%|\\+|'|;])).)*$";
@@ -41,7 +43,7 @@ public class HelperUtils {
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
public static String truncateString(String orgString, int maxLength) {
- if(!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) {
+ if (!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) {
return orgString;
} else {
return orgString.substring(0, maxLength - 4) + "...";
@@ -114,6 +116,9 @@ public class HelperUtils {
return OBJ_MAPPER.readValue(inputStream2String(is), valueTypeRef);
}
+ 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() {
@@ -137,9 +142,50 @@ public class HelperUtils {
};
}
- public static ProtocolResp extends BaseRespStatus> jsonGetProtocolResp(String reqJson,
+ public static ProtocolResp extends BaseRespStatus> jsonGetProtocolResp(String jsonString,
Class subClass) throws JsonProcessingException {
- return OBJ_MAPPER.readValue(reqJson, new TypeReference<>() {
+ 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 JsonParameterizedType.make(ProtocolResp.class,
+ new Type[] {c[0]},
+ ProtocolResp.class.getDeclaringClass());
+ }
+
+ 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;
+ }
+
+ public static ProtocolResp extends BaseRespStatus> jsonGetProtocolResp(String jsonString,
+ Class>[] subClass) throws JsonProcessingException {
+ return OBJ_MAPPER.readValue(jsonString, new TypeReference<>() {
@Override
public Type getType() {
return createRespType(subClass);
@@ -193,7 +239,7 @@ public class HelperUtils {
String localhostIp = "127.0.0.1";
// 客户端与服务器同为一台机器,获取的 ip 有时候是 ipv6 格式
String localhostIpv6 = "0:0:0:0:0:0:0:1";
- String separator = ",";
+ String separator = ",";
if (request == null) {
return "unknown";
diff --git a/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java b/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java
new file mode 100644
index 0000000..46cc931
--- /dev/null
+++ b/src/main/java/com/cmhi/cf/misc/JsonParameterizedType.java
@@ -0,0 +1,112 @@
+package com.cmhi.cf.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;
+
+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 = (Type)(var3 != null ? var3 : var1.getDeclaringClass());
+ this.validateConstructorArguments();
+ }
+
+ private void validateConstructorArguments() {
+ TypeVariable[] var1 = this.rawType.getTypeParameters();
+ if (var1.length != this.actualTypeArguments.length) {
+ throw new MalformedParameterizedTypeException();
+ } else {
+ for(int var2 = 0; var2 < this.actualTypeArguments.length; ++var2) {
+ }
+ }
+ }
+
+ @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.toString());
+ }
+
+ 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;
+ Type[] var3 = this.actualTypeArguments;
+ int var4 = var3.length;
+
+ for(int var5 = 0; var5 < var4; ++var5) {
+ Type var6 = var3[var5];
+ if (!var2) {
+ var1.append(", ");
+ }
+
+ var1.append(var6.getTypeName());
+ var2 = false;
+ }
+
+ var1.append(">");
+ }
+
+ return var1.toString();
+ }
+
+ public static JsonParameterizedType make(Class> var0, Type[] var1, Type var2) {
+ return new JsonParameterizedType(var0, var1, var2);
+ }
+}
diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java b/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java
index 2abd25e..84315b3 100644
--- a/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java
+++ b/src/main/java/com/cmhi/cf/restapi/pojo/base/BasePageResultResp.java
@@ -3,15 +3,19 @@ package com.cmhi.cf.restapi.pojo.base;
import com.cmhi.cf.restapi.pojo.po.PageResults;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"items", "status", "message"})
@Builder
+@NoArgsConstructor
+@AllArgsConstructor
public class BasePageResultResp extends BaseRespStatus {
private PageResults items;
}
diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java b/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java
new file mode 100644
index 0000000..68aff5a
--- /dev/null
+++ b/src/main/java/com/cmhi/cf/restapi/pojo/po/VersionInfo.java
@@ -0,0 +1,19 @@
+package com.cmhi.cf.restapi.pojo.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class VersionInfo {
+ private String commitId;
+ private String commitDescribe;
+ private String commitTime;
+ private String tagName;
+ private String buildTime;
+ private String gitBranch;
+}
diff --git a/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java b/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java
index ec85d66..6e5616b 100644
--- a/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java
+++ b/src/main/java/com/cmhi/cf/restapi/pojo/vo/VersionResp.java
@@ -1,16 +1,20 @@
package com.cmhi.cf.restapi.pojo.vo;
-import com.cmhi.cf.configure.ProjectGitVersionInfo;
import com.cmhi.cf.restapi.pojo.base.BaseRespStatus;
+import com.cmhi.cf.restapi.pojo.po.VersionInfo;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonPropertyOrder({"version", "status", "message"})
@Builder
+@NoArgsConstructor
+@AllArgsConstructor
public class VersionResp extends BaseRespStatus {
- private ProjectGitVersionInfo version;
+ private VersionInfo version;
}
diff --git a/src/test/java/com/cmhi/cf/tools/ToolsTest.java b/src/test/java/com/cmhi/cf/tools/ToolsTest.java
index 4e4af0c..c0760b3 100644
--- a/src/test/java/com/cmhi/cf/tools/ToolsTest.java
+++ b/src/test/java/com/cmhi/cf/tools/ToolsTest.java
@@ -1,9 +1,16 @@
package com.cmhi.cf.tools;
+import com.cmhi.cf.misc.JsonParameterizedType;
+import com.cmhi.cf.restapi.pojo.base.BasePageResultResp;
+import com.cmhi.cf.restapi.pojo.po.OperationLogSummary;
+import com.cmhi.cf.restapi.pojo.vo.ProtocolResp;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.JsonPath;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
+import java.lang.reflect.Type;
import java.util.UUID;
@Slf4j
@@ -27,8 +34,164 @@ public class ToolsTest {
@Test
public void testGenUuid() {
- for(int i = 10; i < 100; i++) {
+ for (int i = 10; i < 100; i++) {
log.info("{}: {}", i, UUID.randomUUID());
}
}
+
+ @Test
+ public void jsonToObject() throws Exception {
+ final String json = """
+ {
+ "ver": 1,
+ "cryptoType": 0,
+ "timeStamp": 1707101107092,
+ "code": 200,
+ "msgContent": {
+ "items": {
+ "pageNumber": 1,
+ "pageSize": 10,
+ "totalPage": 1,
+ "totalRow": 7,
+ "items": [
+ {
+ "id": 1,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 453,
+ "transmitDelay": 139,
+ "operationTime": "2024-02-05T02:23:57.589+00:00"
+ },
+ {
+ "id": 3,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 464,
+ "transmitDelay": 128,
+ "operationTime": "2024-02-05T02:24:32.212+00:00"
+ },
+ {
+ "id": 5,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 435,
+ "transmitDelay": 137,
+ "operationTime": "2024-02-05T02:25:39.344+00:00"
+ },
+ {
+ "id": 7,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 470,
+ "transmitDelay": 129,
+ "operationTime": "2024-02-05T02:26:37.216+00:00"
+ },
+ {
+ "id": 9,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 411,
+ "transmitDelay": 124,
+ "operationTime": "2024-02-05T02:39:48.214+00:00"
+ },
+ {
+ "id": 11,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 468,
+ "transmitDelay": 124,
+ "operationTime": "2024-02-05T02:40:16.012+00:00"
+ },
+ {
+ "id": 13,
+ "module": "系统安全模块",
+ "operationType": "认证/鉴权",
+ "operationStatus": "成功",
+ "description": "[admin] login",
+ "requestIp": "172.21.96.1",
+ "callFunction": "login",
+ "httpMethod": "POST",
+ "httpPath": "/api/login",
+ "userId": 1,
+ "expendTime": 473,
+ "transmitDelay": 121,
+ "operationTime": "2024-02-05T02:45:05.815+00:00"
+ }
+ ]
+ },
+ "status": 0,
+ "message": [
+ "成功"
+ ]
+ }
+ }
+ """;
+
+ ProtocolResp> ret = null;
+
+ JsonParameterizedType type = JsonParameterizedType.make(BasePageResultResp.class,
+ new java.lang.Class[] {OperationLogSummary.class},
+ BasePageResultResp.class.getDeclaringClass());
+
+ ret = new ObjectMapper().readValue(json, new TypeReference<>() {
+ @Override
+ public Type getType() {
+ return JsonParameterizedType.make(ProtocolResp.class,
+ new java.lang.Class[] {(Class) type.getRawType()},
+ ProtocolResp.class.getDeclaringClass());
+ }
+ });
+
+ log.info("{}", ret);
+
+ ret = new ObjectMapper().readValue(json, new TypeReference<>() {
+ });
+
+ log.info("{}", ret);
+
+ Class>[] classes = { String.class, Integer.class, Double.class };
+ }
+
}
diff --git a/src/test/utest/IntegrationTestSuite.java b/src/test/utest/IntegrationTestSuite.java
new file mode 100644
index 0000000..ac1f3c3
--- /dev/null
+++ b/src/test/utest/IntegrationTestSuite.java
@@ -0,0 +1,11 @@
+import com.cmhi.cf.controller.CommonFrameworkApiTest;
+import com.cmhi.cf.controller.OperationLogApiTest;
+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})
+@DisplayName("接口集成测试")
+@Suite
+public class IntegrationTestSuite {
+}
diff --git a/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java b/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java
new file mode 100644
index 0000000..92ed459
--- /dev/null
+++ b/src/test/utest/com/cmhi/cf/common/TestBaseAuthentication.java
@@ -0,0 +1,158 @@
+package com.cmhi.cf.common;
+
+import com.cmhi.cf.authentication.pojo.dto.LoginReq;
+import com.cmhi.cf.authentication.pojo.vo.LoginResp;
+import com.cmhi.cf.misc.HelperUtils;
+import com.cmhi.cf.restapi.config.ProtoCryptoType;
+import com.cmhi.cf.restapi.config.ProtocolConfigure;
+import com.cmhi.cf.restapi.pojo.dto.ProtocolReq;
+import com.cmhi.cf.restapi.pojo.vo.ProtocolResp;
+import com.cmhi.cf.restapi.service.ProtocolSecurityService;
+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;
+
+ @Autowired
+ 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());
+ }
+}
diff --git a/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java b/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java
new file mode 100644
index 0000000..5454d41
--- /dev/null
+++ b/src/test/utest/com/cmhi/cf/common/authentication/TestCommonExtension.java
@@ -0,0 +1,89 @@
+package com.cmhi.cf.common.authentication;
+
+import com.cmhi.cf.authentication.pojo.dto.LoginReq;
+import com.cmhi.cf.misc.HelperUtils;
+import com.cmhi.cf.restapi.config.ProtocolConfigure;
+import com.cmhi.cf.restapi.pojo.dto.ProtocolReq;
+import jakarta.annotation.Resource;
+import lombok.Getter;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultMatcher;
+
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@ExtendWith({SpringExtension.class})
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@AutoConfigureMockMvc
+public class TestCommonExtension implements BeforeEachCallback {
+ @Getter
+ private static final TestRestTemplate restTemplate = new TestRestTemplate();
+ private static final ThreadLocal headersThreadLocal = new ThreadLocal<>();
+
+ @Resource
+ private MockMvc mockMvc;
+
+ public static HttpHeaders getHeaders() {
+ return headersThreadLocal.get();
+ }
+
+
+ @Override
+ public void beforeEach(ExtensionContext extensionContext) throws Exception {
+ 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");
+
+ 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
+ .andExpect((ResultMatcher) content().contentType(
+ MediaType.APPLICATION_JSON)) // Optional: Expect JSON response
+ .andReturn();
+
+// HttpEntity formEntity = new HttpEntity<>(HelperUtils.getJson(loginPro), headers);
+//
+// ResponseEntity response = restTemplate.postForEntity(CommonConfigure.BASEURL + "/api/login", formEntity, String.class);
+// Assertions.assertNotNull(response);
+//
+// ProtocolResp> resp = HelperUtils.jsonGetProtocolResp(response.getBody(), 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);
+//
+// headers.setBearerAuth(loginResp.getToken());
+//
+ headersThreadLocal.set(headers);
+ }
+}
diff --git a/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java b/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java
new file mode 100644
index 0000000..83f7455
--- /dev/null
+++ b/src/test/utest/com/cmhi/cf/controller/CommonFrameworkApiTest.java
@@ -0,0 +1,53 @@
+package com.cmhi.cf.controller;
+
+import com.cmhi.cf.common.ErrorCode;
+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.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
+ void testGetVersion() throws Exception {
+ VersionResp resp = (VersionResp) performanceRestful(RequestMethod.GET, null, "/api/version", new Class[]{VersionResp.class});
+ Assertions.assertNotNull(resp);
+ Assertions.assertNotNull(resp.getVersion());
+ Assertions.assertNotNull(resp.getStatus());
+ Assertions.assertNotNull(resp.getMessage());
+ Assertions.assertNotEquals(resp.getMessage().length, 0);
+ Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode());
+
+ 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
+ void testGetVersionV2() throws Exception {
+ VersionResp resp = (VersionResp) performanceRestful(RequestMethod.POST, null, "/api/version", new Class[]{VersionResp.class});
+ Assertions.assertNotNull(resp);
+ Assertions.assertNotNull(resp.getVersion());
+ Assertions.assertNotNull(resp.getStatus());
+ Assertions.assertNotNull(resp.getMessage());
+ Assertions.assertNotEquals(resp.getMessage().length, 0);
+ Assertions.assertEquals(resp.getStatus(), ErrorCode.ERR_OK.getCode());
+
+ 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/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java b/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java
new file mode 100644
index 0000000..c76bc18
--- /dev/null
+++ b/src/test/utest/com/cmhi/cf/controller/OperationLogApiTest.java
@@ -0,0 +1,80 @@
+package com.cmhi.cf.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.OperationLogReq;
+import com.cmhi.cf.restapi.pojo.po.OperationLogSummary;
+import org.junit.jupiter.api.Assertions;
+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;
+
+import java.util.List;
+
+@ExtendWith({SpringExtension.class})
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@Transactional
+public class OperationLogApiTest extends TestBaseAuthentication {
+ @Test
+ 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;
+ 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());
+
+ 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());
+ });
+ }
+
+ @Test
+ void testGetDetails() throws Exception {
+
+ }
+
+ @Test
+ void testGetDetails_OperationLogServiceReturnsNoItems() throws Exception {
+
+ }
+}