package jnpf.bizcommon.audit.service;
|
|
import jnpf.audit.AuditConsts;
|
import jnpf.audit.model.AuditEventDTO;
|
import jnpf.audit.model.AuditRelatedSignDTO;
|
import jnpf.bizcommon.audit.service.sign.AuditSignEvidence;
|
import jnpf.bizcommon.audit.service.sign.AuditSignEvidenceReader;
|
import jnpf.util.JsonUtil;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.ArgumentCaptor;
|
|
import java.util.Arrays;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
class DataInterfaceSignAuditServiceTest {
|
|
@Test
|
void createsPrimaryAndReviewEventsForDmsFolder() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
Map<String, AuditSignEvidence> evidences = new LinkedHashMap<>();
|
evidences.put("sign-primary", evidence("sign-primary", false));
|
evidences.put("sign-review", evidence("sign-review", true));
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(evidences);
|
AuditEventDTO business = businessEvent();
|
business.setRelatedSigns(Arrays.asList(
|
new AuditRelatedSignDTO("sign-primary", "PRIMARY"),
|
new AuditRelatedSignDTO("sign-review", "REVIEW")));
|
|
service.recordRelatedSign(business);
|
|
ArgumentCaptor<AuditEventDTO> captor = ArgumentCaptor.forClass(AuditEventDTO.class);
|
verify(eventService, org.mockito.Mockito.times(2)).saveIdempotent(captor.capture());
|
List<AuditEventDTO> events = captor.getAllValues();
|
assertTrue(events.get(0).getClientEventId().startsWith("DFS-"));
|
assertTrue(events.get(1).getClientEventId().startsWith("DFS-"));
|
assertEquals("op-1", events.get(0).getOperationId());
|
assertEquals("DMS_FOLDER", events.get(0).getBizType());
|
assertEquals("电子签名", events.get(0).getActionLabel());
|
assertEquals("复审签名", events.get(1).getActionLabel());
|
assertEquals("PRIMARY", JsonUtil.stringToMap(events.get(0).getExtra()).get("signatureRole"));
|
assertEquals("REVIEW", JsonUtil.stringToMap(events.get(1).getExtra()).get("signatureRole"));
|
}
|
|
@Test
|
void rejectsMissingDmsFolderSignatureEvidenceForSpoolRetry() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(java.util.Collections.emptyMap());
|
AuditEventDTO business = businessEvent();
|
business.setRelatedSigns(java.util.Collections.singletonList(
|
new AuditRelatedSignDTO("missing", "PRIMARY")));
|
|
assertThrows(IllegalStateException.class, () -> service.recordRelatedSign(business));
|
}
|
|
@Test
|
void keepsLegacyDataInterfaceIdPrefix() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(java.util.Collections.singletonMap(
|
"legacy-sign", evidence("legacy-sign", false)));
|
AuditEventDTO business = businessEvent();
|
business.setBizType("DATA_INTERFACE");
|
business.setRelatedSignId("legacy-sign");
|
|
service.recordRelatedSign(business);
|
|
ArgumentCaptor<AuditEventDTO> captor = ArgumentCaptor.forClass(AuditEventDTO.class);
|
verify(eventService).saveIdempotent(captor.capture());
|
assertTrue(captor.getValue().getClientEventId().startsWith("DIS-"));
|
}
|
|
@Test
|
void createsValidatedDmsFileSignatureEvent() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(java.util.Collections.singletonMap(
|
"file-sign", evidence("file-sign", false)));
|
AuditEventDTO business = businessEvent();
|
business.setBizType("DMS_FILE");
|
business.setBizCode("MM-R02");
|
business.setTargetTable("dms_documents");
|
business.setTargetId("document-1");
|
business.setRelatedSigns(java.util.Collections.singletonList(
|
new AuditRelatedSignDTO("file-sign", null)));
|
|
service.recordRelatedSign(business);
|
|
ArgumentCaptor<AuditEventDTO> captor = ArgumentCaptor.forClass(AuditEventDTO.class);
|
verify(eventService).saveIdempotent(captor.capture());
|
AuditEventDTO signEvent = captor.getValue();
|
assertTrue(signEvent.getClientEventId().startsWith("DFF-"));
|
assertEquals("DMS_FILE", signEvent.getBizType());
|
assertEquals("电子签名", signEvent.getActionLabel());
|
assertEquals("dms_documents", JsonUtil.stringToMap(signEvent.getExtra())
|
.get("businessTargetTable"));
|
}
|
|
@Test
|
void createsRelatedSignatureForAuditLogBusinessAction() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(java.util.Collections.singletonMap(
|
"loan-sign", evidence("loan-sign", false)));
|
AuditEventDTO business = businessEvent();
|
business.setEventType(AuditConsts.TYPE_BIZ_ACTION);
|
business.setSourceLayer(2);
|
business.setBizType("DMS_LOAN_COPY");
|
business.setActionCode("LOAN_COPY_RECEIVE");
|
business.setRelatedSignId("loan-sign");
|
|
service.recordRelatedSign(business);
|
|
ArgumentCaptor<AuditEventDTO> captor = ArgumentCaptor.forClass(AuditEventDTO.class);
|
verify(eventService).saveIdempotent(captor.capture());
|
AuditEventDTO signEvent = captor.getValue();
|
assertTrue(signEvent.getClientEventId().startsWith("DLC-"));
|
assertEquals(AuditConsts.TYPE_E_SIGNATURE, signEvent.getEventType());
|
assertEquals("电子签名", signEvent.getActionLabel());
|
assertEquals("op-1", signEvent.getOperationId());
|
assertEquals("loan-sign", signEvent.getTargetId());
|
}
|
|
@Test
|
void ignoresSignatureEventsToAvoidGeneratingNestedSignatureFacts() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
AuditEventDTO signature = businessEvent();
|
signature.setEventType(AuditConsts.TYPE_E_SIGNATURE);
|
signature.setRelatedSignId("sign-1");
|
|
service.recordRelatedSign(signature);
|
|
verify(reader, never()).read(anyList(), eq("tenant-1"));
|
verify(eventService, never()).saveIdempotent(org.mockito.ArgumentMatchers.any());
|
}
|
|
@Test
|
@SuppressWarnings("unchecked")
|
void createsOneDmsPermissionSignatureWithAllBatchTargetIds() {
|
AuditSignEvidenceReader reader = mock(AuditSignEvidenceReader.class);
|
AuditEventService eventService = mock(AuditEventService.class);
|
DataInterfaceSignAuditService service = new DataInterfaceSignAuditService(reader, eventService);
|
when(reader.read(anyList(), eq("tenant-1"))).thenReturn(java.util.Collections.singletonMap(
|
"permission-sign", evidence("permission-sign", false)));
|
AuditEventDTO business = businessEvent();
|
business.setBizType("DMS_PERMISSION");
|
business.setBizCode("folder-1");
|
business.setTargetTable("dms_folders");
|
business.setTargetId("folder-1");
|
Map<String, Object> first = new LinkedHashMap<>();
|
first.put("resourceId", "folder-1");
|
Map<String, Object> second = new LinkedHashMap<>();
|
second.put("resourceId", "document-2");
|
Map<String, Object> extra = new LinkedHashMap<>();
|
extra.put("affectedTargets", Arrays.asList(first, second));
|
business.setExtra(JsonUtil.getObjectToString(extra));
|
business.setRelatedSigns(java.util.Collections.singletonList(
|
new AuditRelatedSignDTO("permission-sign", null)));
|
|
service.recordRelatedSign(business);
|
|
ArgumentCaptor<AuditEventDTO> captor = ArgumentCaptor.forClass(AuditEventDTO.class);
|
verify(eventService).saveIdempotent(captor.capture());
|
AuditEventDTO signEvent = captor.getValue();
|
assertTrue(signEvent.getClientEventId().startsWith("DFP-"));
|
assertEquals("DMS_PERMISSION", signEvent.getBizType());
|
assertEquals("电子签名", signEvent.getActionLabel());
|
List<String> targetIds = (List<String>) JsonUtil.stringToMap(signEvent.getExtra())
|
.get("affectedTargetIds");
|
assertEquals(Arrays.asList("folder-1", "document-2"), targetIds);
|
}
|
|
private AuditEventDTO businessEvent() {
|
return AuditEventDTO.builder()
|
.clientEventId("business-1")
|
.operationId("op-1")
|
.eventTime(new Date())
|
.tenantId("tenant-1")
|
.operatorId("user-1")
|
.operatorName("用户一")
|
.appName("jnpf-dms")
|
.bizModule("DMS")
|
.bizType("DMS_FOLDER")
|
.bizCode("folder-1")
|
.targetTable("dms_folders")
|
.targetId("folder-1")
|
.eventType(AuditConsts.TYPE_DATA_CHANGE)
|
.actionCode("UPDATE")
|
.recordTitle("/质量管理/报告")
|
.build();
|
}
|
|
private AuditSignEvidence evidence(String id, boolean review) {
|
return new AuditSignEvidence(id, "account-1", "user-1", "原因", "UPDATE",
|
new Date(), "{\"is_review_button\":" + review + "}");
|
}
|
}
|