package cn.iocoder.yudao.module.system.framework.agent; import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.security.core.LoginUser; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.jupiter.api.Assertions.*; class SystemAgentDelegationServiceTest { private final Map records = new HashMap<>(); private boolean permissionGranted = true; private SystemAgentDelegationService service; @BeforeEach void setUp() { AgentDelegationStore store = new AgentDelegationStore() { @Override public void save(AgentDelegation delegation, long ttlSeconds) { records.put(delegation.getId(), delegation); } @Override public AgentDelegation get(String delegationId) { return records.get(delegationId); } @Override public void delete(String delegationId) { records.remove(delegationId); } }; PermissionCommonApi permissions = new PermissionCommonApi() { @Override public boolean hasAnyPermissions(Long userId, String... permission) { return permissionGranted; } @Override public boolean hasAnyRoles(Long userId, String... roles) { return false; } @Override public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) { return null; } }; service = new SystemAgentDelegationService(store, permissions); ReflectionTestUtils.setField(service, "delegationTtlSeconds", 1800L); login(7L); } @AfterEach void clearContext() { SecurityContextHolder.clearContext(); RequestContextHolder.resetRequestAttributes(); } @Test void issuedTokenStoresOnlySecretHash() { AgentDelegationToken result = issue("task-1"); AgentDelegation stored = records.get(result.delegationId()); assertNotNull(stored); assertFalse(stored.getSecretHash().contains(result.token().substring(result.token().indexOf('.') + 1))); assertEquals("task-1", stored.getTaskId()); assertNotNull(result.expiresAt()); } @Test void rejectsDifferentTaskAndTamperedSecret() { AgentDelegationToken result = issue("task-1"); AgentBridgeException mismatch = assertThrows(AgentBridgeException.class, () -> service.require(result.token(), "task-2", "attachment.read", "mdm:item:import", "mdm.item", 21L)); assertEquals("DELEGATION_SCOPE_MISMATCH", mismatch.getErrorCode()); String tampered = result.token().substring(0, result.token().indexOf('.') + 1) + "tampered"; AgentBridgeException invalid = assertThrows(AgentBridgeException.class, () -> service.require(tampered, "task-1", "attachment.read", "mdm:item:import", "mdm.item", 21L)); assertEquals("DELEGATION_INVALID", invalid.getErrorCode()); } @Test void permissionRevocationInvalidatesExistingToken() { AgentDelegationToken result = issue("task-1"); permissionGranted = false; AgentBridgeException revoked = assertThrows(AgentBridgeException.class, () -> service.require(result.token(), "task-1", "attachment.read", "mdm:item:import", "mdm.item", 21L)); assertEquals("DELEGATION_PERMISSION_REVOKED", revoked.getErrorCode()); } @Test void ownerCanRevokeToken() { AgentDelegationToken result = issue("task-1"); service.revoke(result.delegationId(), 7L); assertFalse(records.containsKey(result.delegationId())); } private AgentDelegationToken issue(String taskId) { return service.issue(taskId, "mdm.item", 21L, Set.of("attachment.read"), "mdm:item:import"); } private static void login(Long userId) { LoginUser loginUser = new LoginUser().setId(userId).setUserType(UserTypeEnum.ADMIN.getValue()); SecurityContextHolder.getContext().setAuthentication( new UsernamePasswordAuthenticationToken(loginUser, null, List.of())); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest())); } }