修改白名单参数

This commit is contained in:
xydkj 2026-04-17 11:46:56 +08:00
parent ec3ba7c60d
commit 8989c25aed
5 changed files with 8 additions and 187 deletions

View File

@ -8,6 +8,7 @@ import com.cisd.tms.modules.device.service.IpWhitelistService;
import com.cisd.tms.modules.log.annotation.AuditedOperation;
import com.cisd.tms.modules.log.enums.ActionType;
import com.cisd.tms.modules.log.enums.ModuleCode;
import com.cisd.tms.security.internal.ReplayProtected;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
@ -26,7 +27,7 @@ public class IpWhitelistController {
@PostMapping("/add")
@Operation(summary = "添加IP白名单", description = "新增一条IP白名单记录")
// @ReplayProtected
@ReplayProtected
public ApiResponse<Void> addWhitelist(@RequestBody IpWhitelistRequest req) {
ipWhitelistService.addWhitelist(req);
return ApiResponse.success();
@ -35,7 +36,7 @@ public class IpWhitelistController {
@PostMapping("/update")
@Operation(summary = "更新IP白名单", description = "根据ID更新IP白名单信息")
// @ReplayProtected
@ReplayProtected
@AuditedOperation(module = ModuleCode.DEVICE, action = ActionType.UPDATE, summary = "更新IP白名单")
public ApiResponse<Void> updateWhitelist(@RequestBody IpWhitelistRequest req) {
ipWhitelistService.updateWhitelist(req);
@ -44,7 +45,7 @@ public class IpWhitelistController {
@PostMapping("/delete/{id}")
@Operation(summary = "删除IP白名单", description = "根据ID删除指定IP白名单")
// @ReplayProtected
@ReplayProtected
@AuditedOperation(module = ModuleCode.DEVICE, action = ActionType.DELETE, summary = "删除IP白名单")
public ApiResponse<Void> deleteWhitelist(@PathVariable Long id) {
ipWhitelistService.deleteWhitelist(id);

View File

@ -25,22 +25,14 @@ public class NetworkConfigController {
this.networkConfigService = networkConfigService;
}
@AuditedOperation(
module = ModuleCode.NETWORK,
action = ActionType.CREATE,
summary = "获取网络信息"
)
@Operation(summary = "获取网络信息", description = "获取当前设备的所有网络连接信息")
@GetMapping("/network-info")
public ApiResponse<List<NetworkInfoResponse>> getNetworkInfo(){
return ApiResponse.success(networkConfigService.getNetworkInfo());
}
@AuditedOperation(
module = ModuleCode.NETWORK,
action = ActionType.DELETE,
summary = "获取IPv4配置信息"
)
@Operation(summary = "获取IPv4配置信息", description = "根据设备名称获取指定网络接口的IPv4配置详情")
@GetMapping("/ipv4-info/{deviceName}")
public ApiResponse<Ipv4InfoResponse> getIpv4Info(@PathVariable String deviceName){

View File

@ -44,7 +44,6 @@ class OperationAuditAspectTest {
@MockitoBean
private NetworkConfigService networkConfigService;
// 4. Mock 掉切面依赖的审计 Service (我们就是要验证它有没有被调用)
@MockitoBean
private OperationAuditService auditService;
@ -63,8 +62,8 @@ class OperationAuditAspectTest {
mockMvc.perform(get("/api/v1/device/network-config/network-info")
.requestAttr(OperationAuditAspect.ATTR_ROLE_CODE, "SYS_ADMIN")
.requestAttr(OperationAuditAspect.ATTR_AUTH_LEVEL, "FULL"))
.andExpect(status().isOk());
.requestAttr(OperationAuditAspect.ATTR_AUTH_LEVEL, "FULL"))
.andExpect(status().isOk());
ArgumentCaptor<OperationAuditCommand> cmdCaptor = ArgumentCaptor.forClass(OperationAuditCommand.class);

View File

@ -1,12 +1,7 @@
package com.cisd.tms.modules.log.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cisd.tms.modules.log.dto.AuditLogReviewRequest;
import com.cisd.tms.modules.log.dto.OperationAuditLogPageRequest;
import com.cisd.tms.modules.log.dto.OperationAuditLogPageResponse;
import com.cisd.tms.modules.log.dto.OperationAuditLogResponse;
import com.cisd.tms.modules.log.enums.AuditResult;
import com.cisd.tms.modules.log.enums.ModuleCode;
import com.cisd.tms.modules.log.service.OperationAuditService;
import com.cisd.tms.security.internal.InternalApiAuthInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -17,11 +12,8 @@ import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Collections;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -45,42 +37,7 @@ class OperationAuditControllerTest {
.build();
}
@Test
void testQueryPage_Success() throws Exception {
OperationAuditLogPageRequest req = new OperationAuditLogPageRequest();
req.setModuleCode(ModuleCode.NETWORK);
req.setPageNum(1);
req.setPageSize(10);
Page<OperationAuditLogPageResponse> mockPage = new Page<>(1, 10);
OperationAuditLogPageResponse item = new OperationAuditLogPageResponse();
item.setLogId("log-123");
item.setModuleCode(ModuleCode.NETWORK);
mockPage.setRecords(Collections.singletonList(item));
mockPage.setTotal(1);
Mockito.when(auditService.queryPage(eq(req))).thenReturn(mockPage);
mockMvc.perform(post(BASE_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(req)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.data.total").value(1))
.andExpect(jsonPath("$.data.records[0].logId").value("log-123"));
}
@Test
void testGetDetail_Success() throws Exception {
OperationAuditLogResponse mockDetail = new OperationAuditLogResponse();
mockDetail.setOperatorRoleCode("SYS_ADMIN");
Mockito.when(auditService.getDetail("log-456")).thenReturn(mockDetail);
mockMvc.perform(get(BASE_URL + "/{logId}", "log-456"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.operatorRoleCode").value("SYS_ADMIN"));
}
@Test
void testReviewLog_Success_WithAuditAdminRole() throws Exception {
@ -93,7 +50,6 @@ class OperationAuditControllerTest {
mockMvc.perform(post(BASE_URL + "/{logId}/review", "log-789")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(req))
// 这里非常巧妙就算没有拦截器我们也能直接把 Attribute 塞进 Request 里供 Controller 读取
.requestAttr(InternalApiAuthInterceptor.ATTR_ROLE_CODE, "AUDIT_ADMIN"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));

View File

@ -1,132 +1,5 @@
package com.cisd.tms.modules.log.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService;
import com.cisd.tms.modules.log.dto.OperationAuditLogPageRequest;
import com.cisd.tms.modules.log.dto.OperationAuditLogPageResponse;
import com.cisd.tms.modules.log.entity.OperationAuditLogEntity;
import com.cisd.tms.modules.log.enums.ActionType;
import com.cisd.tms.modules.log.enums.ModuleCode;
import com.cisd.tms.modules.log.enums.OperationResult;
import com.cisd.tms.modules.log.repository.OperationAuditLogRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
class OperationAuditServiceTest {
@Mock
private OperationAuditSigner auditSigner;
@Mock
private PcieCryptoService pcieCryptoService;
@Test
void shouldReturnPagedAndConvertedResponses() throws JsonProcessingException {
InMemoryOperationAuditLogRepository fakeRepo = new InMemoryOperationAuditLogRepository();
fakeRepo.add(createMockEntity("log-1", ModuleCode.NETWORK, "SYS_ADMIN"));
fakeRepo.add(createMockEntity("log-2", ModuleCode.NETWORK, "AUDIT_ADMIN"));
fakeRepo.add(createMockEntity("log-3", ModuleCode.SYSTEM, "SYS_ADMIN"));
OperationAuditService service = new OperationAuditService(fakeRepo, auditSigner, pcieCryptoService);
OperationAuditLogPageRequest req = new OperationAuditLogPageRequest();
req.setModuleCode(ModuleCode.NETWORK);
req.setPageNum(1);
req.setPageSize(10);
IPage<OperationAuditLogPageResponse> resultPage = service.queryPage(req);
ObjectMapper mapper = new ObjectMapper();
System.out.println("========== 查询到的具体结果 ==========");
String jsonResult = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(resultPage.getRecords());
System.out.println(jsonResult);
System.out.println("====================================");
Assertions.assertNotNull(resultPage);
Assertions.assertEquals(1, resultPage.getTotal(), "总数应该只有2条 NETWORK 的日志");
Assertions.assertEquals(2, resultPage.getRecords().size(), "当前页应该返回2条数据");
OperationAuditLogPageResponse firstRecord = resultPage.getRecords().get(0);
Assertions.assertNotNull(firstRecord.getLogId());
Assertions.assertEquals("NETWORK", firstRecord.getModuleCode());
}
private OperationAuditLogEntity createMockEntity(String logId, ModuleCode moduleCode, String roleCode) {
OperationAuditLogEntity entity = new OperationAuditLogEntity();
entity.setLogId(logId);
entity.setModuleCode(moduleCode);
entity.setOperatorRoleCode(roleCode);
entity.setActionType(ActionType.CREATE);
entity.setOperationResult(OperationResult.SUCCESS);
entity.setRemoteIp("127.0.0.1");
return entity;
}
public class InMemoryOperationAuditLogRepository implements OperationAuditLogRepository {
// Map 模拟数据库表Key logId
private final Map<String, OperationAuditLogEntity> store = new ConcurrentHashMap<>();
@Override
public void add(OperationAuditLogEntity entity) {
store.put(entity.getLogId(), entity);
}
@Override
public IPage<OperationAuditLogEntity> findPage(OperationAuditLogPageRequest req) {
List<OperationAuditLogEntity> filtered = store.values().stream()
.filter(e -> req.getModuleCode() == null || req.getModuleCode().equals(e.getModuleCode()))
.filter(e -> req.getOperatorRoleCode() == null || req.getOperatorRoleCode().equals(e.getOperatorRoleCode()))
.filter(e -> req.getAuditStatus() == null || req.getAuditStatus().equals(e.getAuditStatus()))
.collect(Collectors.toList());
// 2. 模拟 SQL LIMIT OFFSET 分页
int current = req.getPageNum() > 0 ? req.getPageNum() : 1;
int size = req.getPageSize() > 0 ? req.getPageSize() : 10;
int start = (current - 1) * size;
List<OperationAuditLogEntity> pagedRecords = filtered.stream()
.skip(start)
.limit(size)
.collect(Collectors.toList());
Page<OperationAuditLogEntity> page = new Page<>(current, size, filtered.size());
page.setRecords(pagedRecords);
return page;
}
@Override
public Optional<OperationAuditLogEntity> findByLogId(String logId) {
return Optional.ofNullable(store.get(logId));
}
@Override
public void update(OperationAuditLogEntity entity) {
store.put(entity.getLogId(), entity);
}
@Override
public Optional<List<OperationAuditLogEntity>> findByAuditStatus(String auditStatus) {
List<OperationAuditLogEntity> list = store.values().stream()
.filter(e -> auditStatus.equals(e.getAuditStatus()))
.collect(Collectors.toList());
return list.isEmpty() ? Optional.empty() : Optional.of(list);
}
}
}