fix: 统一账号角色校验与默认首页

- 创建与导入账号时强制校验启用角色

- 按启用角色返回默认首页并过滤禁用角色
This commit is contained in:
2026-08-03 14:48:39 +08:00
parent 219e4f7eff
commit 866688b92f
9 changed files with 697 additions and 42 deletions

View File

@@ -2,22 +2,28 @@ package tech.easyflow.admin.controller.system;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import org.testng.annotations.Test;
import tech.easyflow.auth.service.AuthCredentialKeyService;
import tech.easyflow.common.domain.Result;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.admin.controller.system.vo.SysAccountProfileVo;
import tech.easyflow.system.entity.SysAccount;
import tech.easyflow.system.entity.SysRole;
import tech.easyflow.system.service.SysAccountService;
import tech.easyflow.system.service.SysRoleService;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
@@ -28,7 +34,7 @@ import static org.testng.Assert.assertEquals;
public class SysAccountControllerTest {
/**
* 验证创建用户时保留表单选择的部门,而不是替换为操作者部门。
* 验证创建用户时保留表单选择的部门,不被操作者部门覆盖
*/
@Test
public void saveShouldKeepSubmittedDepartment() {
@@ -38,13 +44,28 @@ public class SysAccountControllerTest {
BigInteger operatorId = BigInteger.valueOf(400);
SysAccountService accountService = mock(SysAccountService.class);
AuthCredentialKeyService credentialKeyService = mock(AuthCredentialKeyService.class);
SysAccountController controller = new SysAccountController(accountService, credentialKeyService);
SysRoleService roleService = mock(SysRoleService.class);
SysAccountController controller = new SysAccountController(
accountService,
credentialKeyService,
roleService
);
SysAccount entity = createAccount(selectedDeptId);
LoginAccount loginAccount = createLoginAccount(operatorId, tenantId, operatorDeptId);
AtomicReference<BigInteger> savedDeptId = new AtomicReference<>();
AtomicReference<BigInteger> savedTenantId = new AtomicReference<>();
AtomicReference<BigInteger> savedCreatedBy = new AtomicReference<>();
AtomicReference<BigInteger> savedModifiedBy = new AtomicReference<>();
when(accountService.count(any(QueryWrapper.class))).thenReturn(0L);
when(roleService.listByIds(anyCollection())).thenReturn(List.of(enabledRole(BigInteger.ONE, "user")));
when(accountService.save(any(SysAccount.class))).thenAnswer(invocation -> {
invocation.getArgument(0, SysAccount.class).setId(BigInteger.valueOf(500));
SysAccount savedAccount = invocation.getArgument(0, SysAccount.class);
savedDeptId.set(savedAccount.getDeptId());
savedTenantId.set(savedAccount.getTenantId());
savedCreatedBy.set(savedAccount.getCreatedBy());
savedModifiedBy.set(savedAccount.getModifiedBy());
savedAccount.setId(BigInteger.valueOf(500));
return true;
});
when(credentialKeyService.decryptPayload(any()))
@@ -58,13 +79,107 @@ public class SysAccountControllerTest {
assertEquals(result.getErrorCode(), 0);
}
ArgumentCaptor<SysAccount> accountCaptor = ArgumentCaptor.forClass(SysAccount.class);
verify(accountService).save(accountCaptor.capture());
SysAccount savedAccount = accountCaptor.getValue();
assertEquals(savedAccount.getDeptId(), selectedDeptId);
assertEquals(savedAccount.getTenantId(), tenantId);
assertEquals(savedAccount.getCreatedBy(), operatorId);
assertEquals(savedAccount.getModifiedBy(), operatorId);
verify(accountService).save(any(SysAccount.class));
assertEquals(savedDeptId.get(), selectedDeptId);
assertEquals(savedTenantId.get(), tenantId);
assertEquals(savedCreatedBy.get(), operatorId);
assertEquals(savedModifiedBy.get(), operatorId);
}
/**
* 验证创建用户时拒绝空角色。
*/
@Test
public void saveShouldRejectEmptyRoles() {
SysAccountService accountService = mock(SysAccountService.class);
AuthCredentialKeyService credentialKeyService = mock(AuthCredentialKeyService.class);
SysRoleService roleService = mock(SysRoleService.class);
SysAccountController controller = new SysAccountController(
accountService,
credentialKeyService,
roleService
);
SysAccount entity = createAccount(BigInteger.valueOf(200));
entity.setRoleIds(List.of());
LoginAccount loginAccount = createLoginAccount(
BigInteger.valueOf(400),
BigInteger.valueOf(300),
BigInteger.valueOf(100)
);
when(accountService.count(any(QueryWrapper.class))).thenReturn(0L);
try (MockedStatic<SaTokenUtil> saToken = mockStatic(SaTokenUtil.class)) {
saToken.when(SaTokenUtil::getLoginAccount).thenReturn(loginAccount);
Result<?> result = controller.save(entity);
assertEquals(result.getErrorCode(), 1);
assertEquals(result.getMessage(), "角色不能为空");
}
verify(accountService, never()).save(any(SysAccount.class));
}
/**
* 验证超级管理员默认进入工作台并返回角色标识。
*/
@Test
public void myProfileShouldReturnSuperAdminHomePath() {
BigInteger accountId = BigInteger.ONE;
SysAccountService accountService = mock(SysAccountService.class);
AuthCredentialKeyService credentialKeyService = mock(AuthCredentialKeyService.class);
SysRoleService roleService = mock(SysRoleService.class);
SysAccountController controller = new SysAccountController(
accountService,
credentialKeyService,
roleService
);
SysAccount account = new SysAccount();
account.setId(accountId);
when(accountService.getById(accountId)).thenReturn(account);
when(roleService.getRolesByAccountId(accountId))
.thenReturn(List.of(enabledRole(BigInteger.ONE, "super_admin")));
try (MockedStatic<SaTokenUtil> saToken = mockStatic(SaTokenUtil.class)) {
saToken.when(SaTokenUtil::getLoginAccount)
.thenReturn(createLoginAccount(accountId, BigInteger.ZERO, BigInteger.ZERO));
Result<SysAccountProfileVo> result = controller.myProfile();
assertEquals(result.getData().getHomePath(), "/dashboard/workspace");
assertEquals(result.getData().getRoles(), List.of("super_admin"));
}
}
/**
* 验证普通账号默认进入智能体聊天页。
*/
@Test
public void myProfileShouldReturnAgentChatHomePathForRegularUser() {
BigInteger accountId = BigInteger.valueOf(20);
SysAccountService accountService = mock(SysAccountService.class);
AuthCredentialKeyService credentialKeyService = mock(AuthCredentialKeyService.class);
SysRoleService roleService = mock(SysRoleService.class);
SysAccountController controller = new SysAccountController(
accountService,
credentialKeyService,
roleService
);
SysAccount account = new SysAccount();
account.setId(accountId);
when(accountService.getById(accountId)).thenReturn(account);
when(roleService.getRolesByAccountId(accountId))
.thenReturn(List.of(enabledRole(BigInteger.TWO, "operator")));
try (MockedStatic<SaTokenUtil> saToken = mockStatic(SaTokenUtil.class)) {
saToken.when(SaTokenUtil::getLoginAccount)
.thenReturn(createLoginAccount(accountId, BigInteger.ZERO, BigInteger.ZERO));
Result<SysAccountProfileVo> result = controller.myProfile();
assertEquals(result.getData().getHomePath(), "/ai/agent-chat");
assertEquals(result.getData().getRoles(), List.of("operator"));
}
}
/**
@@ -79,9 +194,25 @@ public class SysAccountControllerTest {
account.setLoginName("department_test_user");
account.setNickname("部门测试用户");
account.setPasswordCredential(Map.of("keyId", "test-key"));
account.setRoleIds(List.of(BigInteger.ONE));
return account;
}
/**
* 构造启用角色。
*
* @param id 角色 ID
* @param roleKey 角色标识
* @return 启用角色
*/
private SysRole enabledRole(BigInteger id, String roleKey) {
SysRole role = new SysRole();
role.setId(id);
role.setRoleKey(roleKey);
role.setStatus(1);
return role;
}
/**
* 构造当前登录账号。
*