This commit is contained in:
2026-08-08 10:31:44 +08:00
parent ced35f1600
commit 2644718b5f
32 changed files with 9710 additions and 31 deletions
@@ -66,6 +66,16 @@ class PlatformTenantControllerContractTest {
returnType.getActualTypeArguments()[0]);
}
@Test
void platformCreationReturnsTenantAndOneTimeAdministratorCredentials() throws Exception {
Method method = PlatformTenantController.class.getMethod("register",
com.baiyue.iam.dto.TenantDtos.RegisterRequest.class, AuthenticatedUser.class);
ParameterizedType returnType = (ParameterizedType) method.getGenericReturnType();
assertEquals(com.baiyue.iam.dto.TenantDtos.CreationResponse.class,
returnType.getActualTypeArguments()[0]);
}
@Test
void shouldExposeCustomerOwnerPasswordResetWithDedicatedPermission() throws Exception {
Method method = PlatformTenantController.class.getMethod("resetOwnerPassword", long.class,
@@ -15,6 +15,7 @@ import com.baiyue.iam.dto.RbacDtos.ChangePermissionStatusRequest;
import com.baiyue.iam.entity.IamMembership;
import com.baiyue.iam.entity.IamPermission;
import com.baiyue.iam.entity.IamRole;
import com.baiyue.iam.entity.IamUser;
import com.baiyue.iam.repository.MemberRepository;
import com.baiyue.iam.repository.RbacRepository;
import org.junit.jupiter.api.Test;
@@ -363,6 +364,47 @@ class RbacServiceTest {
assertEquals("认证会话撤销失败,角色变更未生效", exception.getMessage());
}
@Test
void clearingMemberRolesRevokesThatMembersExistingSessions() {
IamMembership membership = new IamMembership();
membership.setId(31L);
membership.setTenantId(100L);
membership.setUserId(41L);
membership.setMemberType("EMPLOYEE");
IamUser user = new IamUser();
user.setId(41L);
user.setAuthUserId(501L);
when(memberRepository.findById(31L)).thenReturn(membership);
when(memberRepository.findUser(41L)).thenReturn(user);
when(repository.findMemberRoleIds(100L, 31L)).thenReturn(Set.of(11L));
when(repository.findRole(11L, 100L, "MERCHANT"))
.thenReturn(role(11L, 100L, "MERCHANT", "CUSTOM"));
when(authClient.revokeSessions(any(), any())).thenReturn(ApiResponse.success(null));
service.assignRoles(100L, "MERCHANT", new AssignRolesRequest(31L, Set.of()));
verify(repository).replaceMemberRoles(100L, "MERCHANT", 31L, Set.of());
verify(authClient).revokeSessions(eq("test-internal-token"),
eq(new AuthAccountClient.RevokeAccountSessionsRequest(Set.of(501L))));
}
@Test
void savingUnchangedMemberRolesDoesNotRevokeSessions() {
IamMembership membership = new IamMembership();
membership.setId(31L);
membership.setTenantId(100L);
membership.setMemberType("EMPLOYEE");
IamRole role = role(11L, 100L, "MERCHANT", "CUSTOM");
when(memberRepository.findById(31L)).thenReturn(membership);
when(repository.findMemberRoleIds(100L, 31L)).thenReturn(Set.of(11L));
when(repository.findRole(11L, 100L, "MERCHANT")).thenReturn(role);
service.assignRoles(100L, "MERCHANT", new AssignRolesRequest(31L, Set.of(11L)));
verify(repository).replaceMemberRoles(100L, "MERCHANT", 31L, Set.of(11L));
verifyNoInteractions(authClient);
}
private IamRole role(Long id, Long tenantId, String appCode, String roleType) {
IamRole role = new IamRole();
role.setId(id);
@@ -9,6 +9,7 @@ import com.baiyue.iam.entity.IamUser;
import com.baiyue.iam.mapper.IamRoleMapper;
import com.baiyue.iam.repository.MemberRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import jakarta.annotation.Resource;
@@ -18,6 +19,8 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.security.SecureRandom;
import java.util.List;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -43,6 +46,13 @@ class TenantAdministratorProvisioningServiceTest {
@Resource private TenantAdministratorProvisioningService service;
private IamTenant tenant;
@AfterEach
void clearSynchronization() {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
void springContextCreatesBean() {
assertNotNull(service);
@@ -93,6 +103,20 @@ class TenantAdministratorProvisioningServiceTest {
verify(members).replaceRoles(eq(tenant.getId()), anyLong(), eq(List.of(4000100L)));
}
@Test
void platformCreationRollbackCompensatesTheNewAuthAccount() {
TransactionSynchronizationManager.initSynchronization();
var result = service.provisionPlatformCreatedTenant(tenant, 7000L);
List<TransactionSynchronization> synchronizations =
TransactionSynchronizationManager.getSynchronizations();
TransactionSynchronizationManager.clearSynchronization();
synchronizations.forEach(value -> value.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK));
assertTrue(result.created());
verify(auth).compensate("internal-token", result.authUserId());
}
@Test
void existingOwnerSkipsProvisioningAndDoesNotReturnCredentials() {
IamMembership owner = activeOwner();
@@ -26,6 +26,7 @@ class TenantCustomerExportTest {
@MockBean private AuthAccountClient authAccountClient;
@MockBean private TenantApprovalInitializationCoordinator approvalInitialization;
@MockBean private CustomerDimensionRuleInitializationService dimensionRuleInitialization;
@MockBean private TenantAdministratorProvisioningService administratorProvisioning;
@Resource private TenantService service;
@Test
void returnsUnmaskedCustomerRowsAndAdvancingCursor() {
@@ -222,6 +222,9 @@ class TenantServiceTest {
@Test
void platformRegistrationCreatesDraftWithoutCreatingReviewTicket() {
doReturn(TenantAdministratorProvisioningService.ProvisioningResult.created(
81L, "13800138000", "Password1234"))
.when(provisioning).provisionPlatformCreatedTenant(any(), eq(9001L));
var created = service.register(new RegisterRequest(
"Example Merchant", "Example Merchant Ltd", "Bob", "Alice", "13800138000",
@@ -229,12 +232,15 @@ class TenantServiceTest {
LocalDate.of(2020, 1, 2), new BigDecimal("5000000.00"), "CNY", "深圳市南山区", "草稿客户"),
9001L);
assertEquals("PROFILE_REQUIRED", created.status());
assertEquals("Bob", created.legalRepresentative());
assertEquals("基础版", created.servicePackage());
assertEquals("PROFILE_REQUIRED", created.tenant().status());
assertEquals("Bob", created.tenant().legalRepresentative());
assertEquals("基础版", created.tenant().servicePackage());
assertEquals("13800138000", created.administratorUsername());
assertEquals("Password1234", created.temporaryPassword());
verify(repository).insertTenant(argThat(tenant -> Long.valueOf(9001L).equals(tenant.getCreatedBy())
&& Long.valueOf(9001L).equals(tenant.getUpdatedBy())));
verify(dimensionRuleInitialization).initialize(created.id(), 9001L);
verify(dimensionRuleInitialization).initialize(created.tenant().id(), 9001L);
verify(provisioning).provisionPlatformCreatedTenant(any(), eq(9001L));
verify(repository, never()).insertReview(any());
}
@@ -253,16 +259,33 @@ class TenantServiceTest {
@Test
void platformRegistrationAlwaysCreatesTheDraftWithoutACreditCode() {
doReturn(TenantAdministratorProvisioningService.ProvisioningResult.created(
81L, "13800138000", "Password1234"))
.when(provisioning).provisionPlatformCreatedTenant(any(), eq(9001L));
var created = service.register(new RegisterRequest(
"Example Merchant", "Example Merchant Ltd", "Bob", "Alice", "13800138000",
"alice@example.com", "基础版", null, null, 30, null,
null, null, "CNY", null, null), 9001L);
assertEquals(null, created.unifiedSocialCreditCode());
assertEquals(null, created.tenant().unifiedSocialCreditCode());
verify(repository).insertTenant(argThat(tenant -> tenant.getUnifiedSocialCreditCode() == null));
}
@Test
void profileRequiredDraftArchiveDisablesAuthAccountsAndCustomer() {
IamTenant tenant = merchant(10001L, "PROFILE_REQUIRED");
when(repository.findTenantForUpdate(10001L)).thenReturn(tenant);
when(authClient.archiveTenant("internal-token", 10001L))
.thenReturn(com.baiyue.common.core.api.ApiResponse.success(null));
var archived = service.archiveMerchant(10001L);
assertEquals("DISABLED", archived.status());
verify(authClient).archiveTenant("internal-token", 10001L);
verify(repository).saveTenant(tenant);
}
@Test
void explicitSubmissionRequiresOnlyBusinessLicenseAndLegalPersonIdAndCreatesReview() {
IamTenant tenant = merchant(10001L, "PROFILE_REQUIRED");