package jnpf.permission.service.impl;
|
|
import jnpf.base.ActionResult;
|
import jnpf.base.ModuleApi;
|
import jnpf.base.ModuleButtonApi;
|
import jnpf.base.SysConfigApi;
|
import jnpf.base.SystemApi;
|
import jnpf.base.entity.ModuleButtonEntity;
|
import jnpf.base.entity.ModuleEntity;
|
import jnpf.base.entity.SystemEntity;
|
import jnpf.config.ConfigValueUtil;
|
import jnpf.constant.AuthorizeConst;
|
import jnpf.constant.PermissionConst;
|
import jnpf.database.util.DataSourceUtil;
|
import jnpf.database.util.TenantDataSourceUtil;
|
import jnpf.model.tenant.TenantVO;
|
import jnpf.permission.entity.AuthorizeEntity;
|
import jnpf.permission.entity.OrganizeEntity;
|
import jnpf.permission.entity.PositionEntity;
|
import jnpf.permission.entity.RoleEntity;
|
import jnpf.permission.entity.RoleRelationEntity;
|
import jnpf.permission.entity.UserEntity;
|
import jnpf.permission.mapper.OrganizeMapper;
|
import jnpf.permission.mapper.PositionMapper;
|
import jnpf.permission.mapper.RoleMapper;
|
import jnpf.permission.mapper.RoleRelationMapper;
|
import jnpf.permission.mapper.StandingMapper;
|
import jnpf.permission.mapper.UserMapper;
|
import jnpf.permission.mapper.UserRelationMapper;
|
import jnpf.permission.model.authorize.UserPermissionProbe;
|
import jnpf.permission.model.user.UserRelationIds;
|
import jnpf.permission.service.PermissionGroupService;
|
import jnpf.permission.service.UserService;
|
import jnpf.permission.util.UserUtil;
|
import jnpf.util.CacheKeyUtil;
|
import jnpf.util.RedisUtil;
|
import jnpf.util.TenantHolder;
|
import jnpf.util.context.SpringContext;
|
import org.junit.After;
|
import org.junit.Before;
|
import org.junit.Test;
|
import org.junit.runner.RunWith;
|
import org.mockito.InjectMocks;
|
import org.mockito.Mock;
|
import org.mockito.MockedStatic;
|
import org.mockito.Spy;
|
import org.mockito.junit.MockitoJUnitRunner;
|
import org.springframework.context.ApplicationContext;
|
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertTrue;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.mockStatic;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
@RunWith(MockitoJUnitRunner.class)
|
public class UserPermissionProbeServiceTest {
|
|
@Mock private DataSourceUtil dataSourceUtils;
|
@Mock private CacheKeyUtil cacheKeyUtil;
|
@Mock private ConfigValueUtil configValueUtil;
|
@Mock private RedisUtil redisUtil;
|
@Mock private SysConfigApi sysconfigApi;
|
@Mock private ModuleApi moduleApi;
|
@Mock private SystemApi systemApi;
|
@Mock private UserUtil userUtil;
|
@Mock private UserMapper userMapper;
|
@Mock private OrganizeMapper organizeMapper;
|
@Mock private PositionMapper positionMapper;
|
@Mock private RoleMapper roleMapper;
|
@Mock private StandingMapper standingMapper;
|
@Mock private RoleRelationMapper roleRelationMapper;
|
@Mock private UserRelationMapper userRelationMapper;
|
@Mock private PermissionGroupService permissionGroupService;
|
@Mock private UserService userService;
|
@Mock private ModuleButtonApi moduleButtonApi;
|
@Mock private ApplicationContext applicationContext;
|
@Spy
|
@InjectMocks
|
private AuthorizeServiceImpl service;
|
|
private MockedStatic<TenantDataSourceUtil> tenantDataSource;
|
|
@Before
|
public void setUp() {
|
TenantHolder.clearLocalTenantCache();
|
SpringContext.setApplicationContext(applicationContext);
|
tenantDataSource = mockStatic(TenantDataSourceUtil.class);
|
tenantDataSource.when(() -> TenantDataSourceUtil.switchTenant(anyString())).thenAnswer(invocation -> {
|
String tenantId = invocation.getArgument(0);
|
TenantVO tenant = new TenantVO().setEnCode(tenantId).setDbName(tenantId);
|
TenantHolder.setLocalTenantCache(tenant);
|
return tenant;
|
});
|
tenantDataSource.when(TenantDataSourceUtil::clearLocalTenantInfo).thenAnswer(invocation -> {
|
TenantHolder.clearLocalTenantCache();
|
return null;
|
});
|
lenient().when(systemApi.getPermissionTargetCandidates()).thenReturn(ActionResult.success(
|
Collections.singletonList(system("system-lims", "LIMS", 1, 0))));
|
lenient().when(moduleApi.getPermissionTargetCandidates(
|
Collections.singletonList("dianziJiluMubanGuanli")))
|
.thenReturn(ActionResult.success(Collections.singletonList(module("module-1", "system-lims",
|
"dianziJiluMubanGuanli", "Web", 1, 0))));
|
}
|
|
@After
|
public void tearDown() {
|
if (tenantDataSource != null) {
|
tenantDataSource.close();
|
}
|
TenantHolder.clearLocalTenantCache();
|
SpringContext.setApplicationContext(null);
|
}
|
|
@Test
|
public void missingOrDisabledUserIsDenied() {
|
when(userService.getInfo("missing")).thenReturn(null);
|
when(userService.getInfo("disabled")).thenReturn(user(0, 0));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "missing", "btn_edit")), "USER_UNAVAILABLE");
|
assertNull(TenantHolder.getLocalTenantCache());
|
assertDenied(service.probeUserPermission(probe("tenant-a", "disabled", "btn_edit")), "USER_UNAVAILABLE");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void enabledAdministratorIsAllowedWithoutRelations() {
|
when(userService.getInfo("admin")).thenReturn(user(1, 1));
|
|
UserPermissionProbe.Result result = service.probeUserPermission(probe("tenant-a", "admin", "btn_edit"));
|
|
assertTrue(result.isAllowed());
|
assertEquals("ADMINISTRATOR", result.getReasonCode());
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void currentRoleAndPositionAuthorizationsAllowMenuAndButton() {
|
allowUser("user-1", Arrays.asList("position-1"), Arrays.asList("role-1"));
|
List<AuthorizeEntity> authorizations = Arrays.asList(
|
authorization(AuthorizeConst.MODULE, "module-1"),
|
authorization(AuthorizeConst.BUTTON, "button-1"));
|
doAnswer(invocation -> authorizations).when(service).getListByObjectId(anyList());
|
when(moduleButtonApi.getListByModuleIds(any())).thenReturn(Collections.singletonList(button("button-1", "btn_edit", 1)));
|
|
UserPermissionProbe.Result result = service.probeUserPermission(probe("tenant-a", "user-1", "btn_edit"));
|
|
assertTrue(result.isAllowed());
|
assertEquals("ALLOWED", result.getReasonCode());
|
verify(service).getListByObjectId(Arrays.asList("position-1", "role-1"));
|
}
|
|
@Test
|
public void logicalMenuTargetResolvesCurrentModuleIdBeforeAuthorization() {
|
allowUser("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
UserPermissionProbe.Result result = service.probeUserPermission(
|
probe("tenant-a", "user-1", null));
|
|
assertTrue(result.isAllowed());
|
assertEquals("ALLOWED", result.getReasonCode());
|
verify(systemApi).getPermissionTargetCandidates();
|
verify(moduleApi).getPermissionTargetCandidates(Collections.singletonList("dianziJiluMubanGuanli"));
|
}
|
|
@Test
|
public void ambiguousLogicalSystemTargetIsDeniedExplicitly() {
|
when(systemApi.getPermissionTargetCandidates()).thenReturn(ActionResult.success(Arrays.asList(
|
system("system-lims-1", "LIMS", 1, 0),
|
system("system-lims-2", "LIMS", 1, 0))));
|
|
UserPermissionProbe.Result result = service.probeUserPermission(
|
probe("tenant-a", "admin", null));
|
|
assertDenied(result, "SYSTEM_AMBIGUOUS");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void ambiguousLogicalMenuTargetIsDeniedExplicitly() {
|
when(moduleApi.getPermissionTargetCandidates(Collections.singletonList("dianziJiluMubanGuanli")))
|
.thenReturn(ActionResult.success(Arrays.asList(
|
module("module-1", "system-lims", "dianziJiluMubanGuanli", "Web", 1, 0),
|
module("module-2", "system-lims", "dianziJiluMubanGuanli", "Web", 1, 0))));
|
|
UserPermissionProbe.Result result = service.probeUserPermission(
|
probe("tenant-a", "admin", null));
|
|
assertDenied(result, "MODULE_AMBIGUOUS");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void missingDisabledAndDeletedSystemTargetsAreUnavailable() {
|
when(systemApi.getPermissionTargetCandidates()).thenReturn(
|
ActionResult.success(Collections.emptyList()),
|
ActionResult.success(Collections.singletonList(system("system-lims", "LIMS", 0, 0))),
|
ActionResult.success(Collections.singletonList(system("system-lims", "LIMS", 1, 1))));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "SYSTEM_UNAVAILABLE");
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "SYSTEM_UNAVAILABLE");
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "SYSTEM_UNAVAILABLE");
|
}
|
|
@Test
|
public void missingDisabledAndDeletedMenuTargetsAreUnavailable() {
|
when(moduleApi.getPermissionTargetCandidates(Collections.singletonList("dianziJiluMubanGuanli")))
|
.thenReturn(
|
ActionResult.success(Collections.emptyList()),
|
ActionResult.success(Collections.singletonList(module("module-1", "system-lims",
|
"dianziJiluMubanGuanli", "Web", 0, 0))),
|
ActionResult.success(Collections.singletonList(module("module-1", "system-lims",
|
"dianziJiluMubanGuanli", "Web", 1, 1))));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "MODULE_UNAVAILABLE");
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "MODULE_UNAVAILABLE");
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "MODULE_UNAVAILABLE");
|
}
|
|
@Test
|
public void permissionTargetFallbacksAreDependencyFailures() {
|
when(systemApi.getPermissionTargetCandidates()).thenReturn(ActionResult.fail("system unavailable"));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "DEPENDENCY_FAILURE");
|
|
when(systemApi.getPermissionTargetCandidates()).thenReturn(ActionResult.success(
|
Collections.singletonList(system("system-lims", "LIMS", 1, 0))));
|
when(moduleApi.getPermissionTargetCandidates(Collections.singletonList("dianziJiluMubanGuanli")))
|
.thenReturn(ActionResult.fail("module unavailable"));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "admin", null)), "DEPENDENCY_FAILURE");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void disabledPositionDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.<String>emptyList());
|
lenient().when(positionMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(position("position-1", 0, 0)));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenReturn(Collections.emptyList());
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void deletedPositionDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.<String>emptyList());
|
lenient().when(positionMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(position("position-1", 1, 1)));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenReturn(Collections.emptyList());
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void disabledRoleDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("user-1", PermissionConst.USER, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 0, 0)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void deletedRoleDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("user-1", PermissionConst.USER, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 1, 1)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void roleDerivedOnlyFromDisabledPositionDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.singletonList("role-1"));
|
lenient().when(positionMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(position("position-1", 0, 0)));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("position-1", PermissionConst.POSITION, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 1, 0)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void roleDerivedOnlyFromDeletedPositionDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.singletonList("role-1"));
|
lenient().when(positionMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(position("position-1", 1, 1)));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("position-1", PermissionConst.POSITION, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 1, 0)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void roleDerivedOnlyFromDisabledOrganizationDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
lenient().when(organizeMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(organize("organize-ignored", 0, 0)));
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("organize-ignored", PermissionConst.ORGANIZE, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 1, 0)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void roleRelationWithMismatchedSourceTypeDoesNotAuthorize() {
|
stubUserRelations("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(Collections.singletonList(roleRelation("user-1", PermissionConst.POSITION, "role-1")));
|
lenient().when(roleMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(role("role-1", 1, 0)));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void nullPositionQueryFailsClosed() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.<String>emptyList());
|
lenient().when(positionMapper.getListByIds(anyList())).thenReturn(null);
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenReturn(Collections.emptyList());
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
UserPermissionProbe.Result result = service.probeUserPermission(probe("tenant-a", "user-1", null));
|
|
assertFalse(result.isAllowed());
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void positionQueryExceptionFailsClosedAndClearsTenant() {
|
stubUserRelations("user-1", Collections.singletonList("position-1"), Collections.<String>emptyList());
|
lenient().when(positionMapper.getListByIds(anyList())).thenThrow(new IllegalStateException("query failed"));
|
lenient().doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "DEPENDENCY_FAILURE");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void removingCurrentRoleIsObservedOnNextProbe() {
|
AtomicReference<List<String>> roles = new AtomicReference<>(Collections.singletonList("role-1"));
|
when(userService.getInfo("user-1")).thenReturn(user(1, 0));
|
when(userService.getUserObjectIdList("user-1"))
|
.thenAnswer(invocation -> relations(Collections.<String>emptyList(), roles.get()));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenAnswer(invocation ->
|
roleRelations("user-1", PermissionConst.USER, roles.get()));
|
lenient().when(roleMapper.getListByIds(anyList())).thenAnswer(invocation ->
|
roles(((List<String>) invocation.getArgument(0))));
|
doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertTrue(service.probeUserPermission(probe("tenant-a", "user-1", null)).isAllowed());
|
roles.set(Collections.<String>emptyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void removingCurrentPositionIsObservedOnNextProbe() {
|
AtomicReference<List<String>> positions = new AtomicReference<>(Collections.singletonList("position-1"));
|
when(userService.getInfo("user-1")).thenReturn(user(1, 0));
|
when(userService.getUserObjectIdList("user-1"))
|
.thenAnswer(invocation -> relations(positions.get(), Collections.<String>emptyList()));
|
lenient().when(positionMapper.getListByIds(anyList())).thenAnswer(invocation ->
|
positions(((List<String>) invocation.getArgument(0))));
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenReturn(Collections.emptyList());
|
doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertTrue(service.probeUserPermission(probe("tenant-a", "user-1", null)).isAllowed());
|
positions.set(Collections.<String>emptyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
}
|
|
@Test
|
public void removingAuthorizationIsObservedOnNextProbe() {
|
allowUser("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
AtomicReference<List<AuthorizeEntity>> authorizations = new AtomicReference<>(menuAuthorization());
|
doAnswer(invocation -> authorizations.get()).when(service).getListByObjectId(anyList());
|
|
assertTrue(service.probeUserPermission(probe("tenant-a", "user-1", null)).isAllowed());
|
authorizations.set(Collections.<AuthorizeEntity>emptyList());
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_AUTHORIZATION");
|
}
|
|
@Test
|
public void disabledButtonFailsClosed() {
|
allowUser("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
doAnswer(invocation -> Arrays.asList(
|
authorization(AuthorizeConst.MODULE, "module-1"),
|
authorization(AuthorizeConst.BUTTON, "button-1")))
|
.when(service).getListByObjectId(anyList());
|
when(moduleButtonApi.getListByModuleIds(any())).thenReturn(Collections.singletonList(button("button-1", "btn_edit", 0)));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", "btn_edit")), "BUTTON_UNAVAILABLE");
|
}
|
|
@Test
|
public void emptyButtonCodeOnlyChecksMenuPermission() {
|
allowUser("user-1", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
UserPermissionProbe.Result result = service.probeUserPermission(probe("tenant-a", "user-1", ""));
|
|
assertTrue(result.isAllowed());
|
assertEquals("ALLOWED", result.getReasonCode());
|
}
|
|
@Test
|
public void tenantRelationsCannotBeReusedAcrossSequentialProbes() {
|
when(userService.getInfo("user-1")).thenAnswer(invocation -> user(1, 0));
|
when(userService.getUserObjectIdList("user-1")).thenAnswer(invocation -> {
|
if ("tenant-a".equals(TenantHolder.getDatasourceId())) {
|
return relations(Collections.<String>emptyList(), Collections.singletonList("role-a"));
|
}
|
return relations(Collections.<String>emptyList(), Collections.<String>emptyList());
|
});
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any())).thenAnswer(invocation -> {
|
if ("tenant-a".equals(TenantHolder.getDatasourceId())) {
|
return Collections.singletonList(roleRelation("user-1", PermissionConst.USER, "role-a"));
|
}
|
return Collections.emptyList();
|
});
|
lenient().when(roleMapper.getListByIds(anyList())).thenAnswer(invocation ->
|
roles(((List<String>) invocation.getArgument(0))));
|
doAnswer(invocation -> menuAuthorization()).when(service).getListByObjectId(anyList());
|
|
assertTrue(service.probeUserPermission(probe("tenant-a", "user-1", null)).isAllowed());
|
assertNull(TenantHolder.getLocalTenantCache());
|
assertDenied(service.probeUserPermission(probe("tenant-b", "user-1", null)), "NO_CURRENT_RELATION");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
@Test
|
public void nullDependencyResponsesFailClosed() {
|
when(userService.getInfo("user-1")).thenReturn(user(1, 0));
|
when(userService.getUserObjectIdList("user-1")).thenReturn(null);
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "NO_CURRENT_RELATION");
|
|
allowUser("user-2", Collections.<String>emptyList(), Collections.singletonList("role-1"));
|
doAnswer(invocation -> Arrays.asList(
|
authorization(AuthorizeConst.MODULE, "module-1"),
|
authorization(AuthorizeConst.BUTTON, "button-1")))
|
.when(service).getListByObjectId(anyList());
|
when(moduleButtonApi.getListByModuleIds(any())).thenReturn(null);
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-2", "btn_edit")), "BUTTON_UNAVAILABLE");
|
}
|
|
@Test
|
public void dependencyExceptionFailsClosedAndClearsTenant() {
|
when(userService.getInfo("user-1")).thenThrow(new IllegalStateException("query failed"));
|
|
assertDenied(service.probeUserPermission(probe("tenant-a", "user-1", null)), "DEPENDENCY_FAILURE");
|
assertNull(TenantHolder.getLocalTenantCache());
|
}
|
|
private void allowUser(String userId, List<String> positions, List<String> roles) {
|
stubUserRelations(userId, positions, roles);
|
if (!positions.isEmpty()) {
|
lenient().when(positionMapper.getListByIds(anyList())).thenReturn(positions(positions));
|
}
|
stubActiveOrganizations();
|
lenient().when(roleRelationMapper.getListByObjectId(anyList(), any()))
|
.thenReturn(roleRelations(userId, PermissionConst.USER, roles));
|
if (!roles.isEmpty()) {
|
lenient().when(roleMapper.getListByIds(anyList())).thenReturn(roles(roles));
|
}
|
}
|
|
private void stubUserRelations(String userId, List<String> positions, List<String> roles) {
|
when(userService.getInfo(userId)).thenReturn(user(1, 0));
|
when(userService.getUserObjectIdList(userId)).thenReturn(relations(positions, roles));
|
}
|
|
private void stubActiveOrganizations() {
|
lenient().when(organizeMapper.getListByIds(anyList()))
|
.thenReturn(Collections.singletonList(organize("organize-ignored", 1, 0)));
|
}
|
|
private UserPermissionProbe probe(String tenantId, String userId, String buttonCode) {
|
UserPermissionProbe probe = new UserPermissionProbe();
|
probe.setTenantId(tenantId);
|
probe.setUserId(userId);
|
probe.setSystemCode("LIMS");
|
probe.setModuleCode("dianziJiluMubanGuanli");
|
probe.setModuleCategory("Web");
|
probe.setButtonCode(buttonCode);
|
return probe;
|
}
|
|
private SystemEntity system(String id, String code, int enabledMark, int deleteMark) {
|
SystemEntity system = new SystemEntity();
|
system.setId(id);
|
system.setEnCode(code);
|
system.setEnabledMark(enabledMark);
|
system.setDeleteMark(deleteMark);
|
return system;
|
}
|
|
private ModuleEntity module(String id, String systemId, String code, String category,
|
int enabledMark, int deleteMark) {
|
ModuleEntity module = new ModuleEntity();
|
module.setId(id);
|
module.setSystemId(systemId);
|
module.setEnCode(code);
|
module.setCategory(category);
|
module.setEnabledMark(enabledMark);
|
module.setDeleteMark(deleteMark);
|
return module;
|
}
|
|
private UserEntity user(int enabledMark, int administrator) {
|
UserEntity user = new UserEntity();
|
user.setEnabledMark(enabledMark);
|
user.setIsAdministrator(administrator);
|
return user;
|
}
|
|
private UserRelationIds relations(List<String> positions, List<String> roles) {
|
return UserRelationIds.builder()
|
.group(Collections.singletonList("group-ignored"))
|
.organize(Collections.singletonList("organize-ignored"))
|
.position(new ArrayList<>(positions))
|
.role(new ArrayList<>(roles))
|
.build();
|
}
|
|
private List<PositionEntity> positions(List<String> ids) {
|
List<PositionEntity> result = new ArrayList<>();
|
for (String id : ids) {
|
result.add(position(id, 1, 0));
|
}
|
return result;
|
}
|
|
private PositionEntity position(String id, int enabledMark, int deleteMark) {
|
PositionEntity position = new PositionEntity();
|
position.setId(id);
|
position.setEnabledMark(enabledMark);
|
position.setDeleteMark(deleteMark);
|
return position;
|
}
|
|
private List<RoleEntity> roles(List<String> ids) {
|
List<RoleEntity> result = new ArrayList<>();
|
for (String id : ids) {
|
result.add(role(id, 1, 0));
|
}
|
return result;
|
}
|
|
private RoleEntity role(String id, int enabledMark, int deleteMark) {
|
RoleEntity role = new RoleEntity();
|
role.setId(id);
|
role.setEnabledMark(enabledMark);
|
role.setDeleteMark(deleteMark);
|
return role;
|
}
|
|
private OrganizeEntity organize(String id, int enabledMark, int deleteMark) {
|
OrganizeEntity organize = new OrganizeEntity();
|
organize.setId(id);
|
organize.setEnabledMark(enabledMark);
|
organize.setDeleteMark(deleteMark);
|
return organize;
|
}
|
|
private List<RoleRelationEntity> roleRelations(String objectId, String objectType, List<String> roleIds) {
|
List<RoleRelationEntity> result = new ArrayList<>();
|
for (String roleId : roleIds) {
|
result.add(roleRelation(objectId, objectType, roleId));
|
}
|
return result;
|
}
|
|
private RoleRelationEntity roleRelation(String objectId, String objectType, String roleId) {
|
RoleRelationEntity relation = new RoleRelationEntity();
|
relation.setObjectId(objectId);
|
relation.setObjectType(objectType);
|
relation.setRoleId(roleId);
|
return relation;
|
}
|
|
private List<AuthorizeEntity> menuAuthorization() {
|
return Collections.singletonList(authorization(AuthorizeConst.MODULE, "module-1"));
|
}
|
|
private AuthorizeEntity authorization(String type, String itemId) {
|
AuthorizeEntity entity = new AuthorizeEntity();
|
entity.setItemType(type);
|
entity.setItemId(itemId);
|
return entity;
|
}
|
|
private ModuleButtonEntity button(String id, String code, int enabledMark) {
|
ModuleButtonEntity button = new ModuleButtonEntity();
|
button.setId(id);
|
button.setEnCode(code);
|
button.setEnabledMark(enabledMark);
|
return button;
|
}
|
|
private void assertDenied(UserPermissionProbe.Result result, String reasonCode) {
|
assertFalse(result.isAllowed());
|
assertEquals(reasonCode, result.getReasonCode());
|
}
|
}
|