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<String, AgentDelegation> 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()));
|
}
|
}
|