diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImpl.java index b45225fd..97dfc6c9 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImpl.java @@ -1,11 +1,5 @@ package com.red.circle.other.infra.gateway.user; -import com.red.circle.other.domain.gateway.user.UserProfileGateway; -import com.red.circle.other.domain.model.user.UserProfile; -import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService; -import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember; -import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService; -import com.red.circle.other.infra.database.rds.service.sys.EnumConfigService; import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService; import com.red.circle.other.infra.database.rds.service.user.user.ExpandService; import com.red.circle.tool.core.text.StringUtils; @@ -15,7 +9,6 @@ import com.red.circle.other.infra.database.rds.service.user.device.DeviceRegiste import com.red.circle.other.infra.database.rds.service.user.device.IpRegisterQuantityService; import com.red.circle.other.inner.model.cmd.user.IncrDeviceRegisterCmd; import com.red.circle.other.inner.model.cmd.user.device.AllowDeviceRegisterCmd; -import com.red.circle.other.inner.enums.config.EnumConfigKey; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -31,9 +24,6 @@ public class RegisterDeviceGatewayImpl implements RegisterDeviceGateway { private final IpRegisterQuantityService ipRegisterQuantityService; private final DeviceRegisterQuantityService deviceRegisterQuantityService; private final LatestMobileDeviceService latestMobileDeviceService; - private final UserProfileGateway userProfileGateway; - private final TeamMemberService teamMemberService; - private final EnumConfigCacheService enumConfigCacheService; private final ExpandService expandService; /** @@ -95,71 +85,13 @@ public class RegisterDeviceGatewayImpl implements RegisterDeviceGateway { return false; } + // 运营手动黑白名单仍然生效:BLOCK 强制拦截、显式放行返回 false。 String status = checkDeviceListStatus(userId); if (status != null) { return "BLOCK".equals(status); } - UserProfile userProfile = userProfileGateway.getByUserId(userId); - if (userProfile == null) { - return false; - } - - String fingerprint = latestMobileDeviceService.getDeviceFingerprintAndIPByUserId(userId); - if (StringUtils.isBlank(fingerprint)) { - return false; - } - - // 跳过白名单用户 - String whitelistConfig = enumConfigCacheService.getValue( - EnumConfigKey.DEVICE_REGISTER_WHITELIST, userProfile.getOriginSys()); - if (matchDeviceWhitelist(whitelistConfig, String.valueOf(userProfile.getAccount()))) { - return false; - } - - java.util.List userIds = latestMobileDeviceService.listUserIdsByDeviceFingerprint( - fingerprint, userProfile.getOriginSys()); - - if (userIds == null || userIds.isEmpty()) { - return false; - } - - for (Long otherUserId : userIds) { - if (java.util.Objects.equals(otherUserId, userId)) { - continue; - } - - // 判断是否为主播:检查用户是否为团队成员 - TeamMember teamMember = - teamMemberService.getByMemberId(otherUserId); - if (teamMember == null) { - continue; - } - - // 同设备账号已被封禁(checkAccountArchive)或已注销(profile 为 null)的,不再占用该设备的主播/代理名额 - UserProfile otherProfile = userProfileGateway.getByUserId(otherUserId); - if (otherProfile == null || otherProfile.checkAccountArchive()) { - continue; - } - - return true; - } - - return false; - } - - /** - * 设备白名单按分隔符切分后精确比对账号,避免子串误命中(如账号 123 被白名单 51234 命中). - */ - private boolean matchDeviceWhitelist(String whitelistConfig, String account) { - if (StringUtils.isBlank(whitelistConfig) || StringUtils.isBlank(account)) { - return false; - } - for (String item : whitelistConfig.split("[,,;;\\s]+")) { - if (account.equals(item.trim())) { - return true; - } - } + // 业务调整:不再按设备指纹限制同设备成为主播/代理,设备维度全部放行。 return false; } diff --git a/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImplTest.java b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImplTest.java index 4ed35df8..e9969dc2 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImplTest.java +++ b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/gateway/user/RegisterDeviceGatewayImplTest.java @@ -2,135 +2,56 @@ package com.red.circle.other.infra.gateway.user; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import com.red.circle.common.business.enums.AccountStatusEnum; -import com.red.circle.other.domain.gateway.user.UserProfileGateway; -import com.red.circle.other.domain.model.user.UserProfile; -import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService; -import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember; -import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService; import com.red.circle.other.infra.database.rds.service.user.device.DeviceRegisterQuantityService; import com.red.circle.other.infra.database.rds.service.user.device.IpRegisterQuantityService; import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService; import com.red.circle.other.infra.database.rds.service.user.user.ExpandService; -import com.red.circle.tool.core.date.TimestampUtils; -import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class RegisterDeviceGatewayImplTest { - private static final Long SELF_ID = 100L; - private static final Long OTHER_ID = 200L; - private static final String FINGERPRINT = "Android|Infinix X6871|1.2.3.4"; + private static final Long USER_ID = 100L; - private IpRegisterQuantityService ipRegisterQuantityService; - private DeviceRegisterQuantityService deviceRegisterQuantityService; private LatestMobileDeviceService latestMobileDeviceService; - private UserProfileGateway userProfileGateway; - private TeamMemberService teamMemberService; - private EnumConfigCacheService enumConfigCacheService; private ExpandService expandService; private RegisterDeviceGatewayImpl gateway; @BeforeEach void setUp() { - ipRegisterQuantityService = mock(IpRegisterQuantityService.class); - deviceRegisterQuantityService = mock(DeviceRegisterQuantityService.class); latestMobileDeviceService = mock(LatestMobileDeviceService.class); - userProfileGateway = mock(UserProfileGateway.class); - teamMemberService = mock(TeamMemberService.class); - enumConfigCacheService = mock(EnumConfigCacheService.class); expandService = mock(ExpandService.class); gateway = new RegisterDeviceGatewayImpl( - ipRegisterQuantityService, - deviceRegisterQuantityService, + mock(IpRegisterQuantityService.class), + mock(DeviceRegisterQuantityService.class), latestMobileDeviceService, - userProfileGateway, - teamMemberService, - enumConfigCacheService, expandService); - - when(expandService.getDeviceListBlock(anyLong())).thenReturn(null); - when(userProfileGateway.getByUserId(SELF_ID)).thenReturn(profile(SELF_ID, "1001", AccountStatusEnum.NORMAL, 0)); - when(latestMobileDeviceService.getDeviceFingerprintAndIPByUserId(SELF_ID)).thenReturn(FINGERPRINT); - when(latestMobileDeviceService.listUserIdsByDeviceFingerprint(FINGERPRINT, "LIKEI")) - .thenReturn(List.of(SELF_ID, OTHER_ID)); - when(teamMemberService.getByMemberId(OTHER_ID)).thenReturn(new TeamMember().setMemberId(OTHER_ID)); - } - - private UserProfile profile(Long id, String account, AccountStatusEnum status, int freezeDays) { - UserProfile profile = new UserProfile(); - profile.setId(id); - profile.setAccount(account); - profile.setOriginSys("LIKEI"); - profile.setAccountStatus(status.name()); - profile.setFreezingTime(freezeDays == 0 ? TimestampUtils.now() : TimestampUtils.nowPlusDays(freezeDays)); - return profile; } @Test - void blocksWhenSameDeviceHasActiveTeamMember() { - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(profile(OTHER_ID, "1002", AccountStatusEnum.NORMAL, 0)); + void deviceFingerprintNoLongerBlocks() { + // 业务调整:设备维度全部放行,不再查询指纹关联 + when(expandService.getDeviceListBlock(USER_ID)).thenReturn(null); - assertTrue(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); + assertFalse(gateway.checkDeviceFingerprintHasAnchor(USER_ID)); + verifyNoInteractions(latestMobileDeviceService); } @Test - void exemptsArchivedAccountOnSameDevice() { - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(profile(OTHER_ID, "1002", AccountStatusEnum.ARCHIVE, 365)); + void manualDeviceListStillWorks() { + when(expandService.getDeviceListBlock(USER_ID)).thenReturn(Boolean.TRUE); + assertTrue(gateway.checkDeviceFingerprintHasAnchor(USER_ID)); - assertFalse(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); + when(expandService.getDeviceListBlock(USER_ID)).thenReturn(Boolean.FALSE); + assertFalse(gateway.checkDeviceFingerprintHasAnchor(USER_ID)); } @Test - void exemptsArchiveDeviceAccountOnSameDevice() { - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(profile(OTHER_ID, "1002", AccountStatusEnum.ARCHIVE_DEVICE, 0)); - - assertFalse(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - } - - @Test - void exemptsDeletedAccountOnSameDevice() { - // 已注销账号 getByUserId 返回 null(逻辑删过滤),不应永久占用设备名额 - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(null); - - assertFalse(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - } - - @Test - void expiredArchiveStillBlocks() { - // ARCHIVE 但冻结期已过 = 已自动解封,重新占用名额 - UserProfile expired = profile(OTHER_ID, "1002", AccountStatusEnum.ARCHIVE, 0); - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(expired); - - assertTrue(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - } - - @Test - void whitelistMatchesExactAccountOnly() { - when(userProfileGateway.getByUserId(OTHER_ID)).thenReturn(profile(OTHER_ID, "1002", AccountStatusEnum.NORMAL, 0)); - - // 子串不再误命中:白名单 51001 不应豁免账号 1001 - when(enumConfigCacheService.getValue(com.red.circle.other.inner.enums.config.EnumConfigKey.DEVICE_REGISTER_WHITELIST, "LIKEI")) - .thenReturn("51001,9999"); - assertTrue(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - - // 精确命中豁免 - when(enumConfigCacheService.getValue(com.red.circle.other.inner.enums.config.EnumConfigKey.DEVICE_REGISTER_WHITELIST, "LIKEI")) - .thenReturn("51001,1001"); - assertFalse(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - } - - @Test - void manualDeviceListOverridesFingerprintLogic() { - when(expandService.getDeviceListBlock(SELF_ID)).thenReturn(Boolean.TRUE); - assertTrue(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); - - when(expandService.getDeviceListBlock(SELF_ID)).thenReturn(Boolean.FALSE); - assertFalse(gateway.checkDeviceFingerprintHasAnchor(SELF_ID)); + void nullUserIdIsAllowed() { + assertFalse(gateway.checkDeviceFingerprintHasAnchor(null)); } }