日志记录提交

This commit is contained in:
2026-08-05 14:20:04 +08:00
parent 264458920b
commit 06f7f9d2f2
83 changed files with 3256 additions and 27 deletions
@@ -0,0 +1,39 @@
package com.baiyue.audit.service;
import com.baiyue.audit.dto.AuditIngestRequest;
import com.baiyue.audit.repository.AuditEventRepository;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.time.Instant;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SpringJUnitConfig(AuditIngestService.class)
class AuditIngestIdempotencyTest {
@MockBean
private AuditEventRepository repository;
@Resource
private AuditIngestService service;
@Test
void keepsStableEventIdForMqRedelivery() {
AuditIngestRequest request = request("audit-1");
when(repository.save(request, "audit-1")).thenReturn(false);
assertThat(service.ingest(request)).isFalse();
verify(repository).save(request, "audit-1");
}
private static AuditIngestRequest request(String eventId) {
return new AuditIngestRequest(eventId, "ROLE_UPDATE", "ROLE", "1", "修改角色",
"request-1", "trace-1", 1L, 1L, 1L, "admin", "PLATFORM", "WEB", "PUT",
"/roles/1", "127.0.0.1", 10, true, null, null, null, null,
Instant.parse("2026-08-05T00:00:00Z"), "iam-service");
}
}
@@ -0,0 +1,90 @@
package com.baiyue.audit.service;
import com.baiyue.audit.dto.AuditLogQuery;
import com.baiyue.audit.dto.AuditLogResponses;
import com.baiyue.audit.entity.AuditLogEntity;
import com.baiyue.audit.repository.AuditEventRepository;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.exception.BizException;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;
@SpringJUnitConfig(AuditLogQueryService.class)
class AuditLogQueryServiceTest {
@MockBean
private AuditEventRepository repository;
@Resource
private AuditLogQueryService service;
@Test
void pageDoesNotExposeSnapshots() {
AuditLogQuery query = new AuditLogQuery(10001L, 7L, "ROLE_UPDATE", "ROLE", "9", true,
null, null, "管理员");
when(repository.page(query, 1, 20)).thenReturn(new PageResult<>(List.of(log(8L)), 1, 20, 1, 1));
PageResult<AuditLogResponses.ListItem> result = service.page(query, 1, 20);
assertThat(result.records()).singleElement().satisfies(item -> {
assertThat(item.id()).isEqualTo(8L);
assertThat(item.accountId()).isEqualTo(10001L);
assertThat(item.eventType()).isEqualTo("ROLE_UPDATE");
});
assertThat(AuditLogResponses.ListItem.class.getRecordComponents())
.extracting(component -> component.getName())
.doesNotContain("beforeData", "afterData");
}
@Test
void detailReturnsSanitizedSnapshots() {
when(repository.findById(8L)).thenReturn(log(8L));
AuditLogResponses.Detail detail = service.detail(8L);
assertThat(detail.beforeData()).isEqualTo("{\"name\":\"旧角色\"}");
assertThat(detail.afterData()).isEqualTo("{\"name\":\"新角色\"}");
}
@Test
void missingLogIsReportedAsNotFound() {
when(repository.findById(8L)).thenReturn(null);
assertThatThrownBy(() -> service.detail(8L)).isInstanceOf(BizException.class)
.hasMessage("操作日志不存在");
}
private static AuditLogEntity log(Long id) {
AuditLogEntity entity = new AuditLogEntity();
entity.setId(id);
entity.setEventId("audit-8");
entity.setEventType("ROLE_UPDATE");
entity.setResourceType("ROLE");
entity.setResourceId("9");
entity.setDescription("管理员修改角色权限");
entity.setTenantId(10001L);
entity.setOperatorTenantId(0L);
entity.setUserId(7L);
entity.setUsername("管理员");
entity.setAppCode("PLATFORM");
entity.setClientType("WEB");
entity.setRequestId("request-8");
entity.setTraceId("trace-8");
entity.setSuccess(true);
entity.setBeforeData("{\"name\":\"旧角色\"}");
entity.setAfterData("{\"name\":\"新角色\"}");
entity.setServiceName("iam-service");
entity.setOccurredAt(Instant.parse("2026-08-05T10:00:00Z"));
entity.setCreatedAt(LocalDateTime.of(2026, 8, 5, 18, 0));
return entity;
}
}