PasswordServiceTest 추가 - 최근 비밀번호 중복 검사 로직 수정
TestCleanupService 확장 - 초대/회원 소속 관리 메서드 구현 API 추가 - 초대 삭제 및 소속 제외, 사용자 존재 여부 확인
This commit is contained in:
@@ -34,7 +34,8 @@ public class PasswordService {
|
|||||||
.orElseThrow(() -> new IllegalArgumentException("해당 사용자를 찾을 수 없습니다."));
|
.orElseThrow(() -> new IllegalArgumentException("해당 사용자를 찾을 수 없습니다."));
|
||||||
|
|
||||||
validatePasswordUpdate(user, newPassword, confirmPassword);
|
validatePasswordUpdate(user, newPassword, confirmPassword);
|
||||||
checkPasswordHistory(user.getLoginId(), newPassword);
|
// PTL_USER_PASSWORD_HISTORY.USER_ID 에는 loginId가 아닌 PortalUser.id가 저장된다.
|
||||||
|
checkPasswordHistory(user.getId(), newPassword);
|
||||||
|
|
||||||
List<UserPasswordHistory> histories = passwordHistoryRepository.findRecentPasswordsByUserId(user.getId());
|
List<UserPasswordHistory> histories = passwordHistoryRepository.findRecentPasswordsByUserId(user.getId());
|
||||||
if(histories.isEmpty()) {
|
if(histories.isEmpty()) {
|
||||||
|
|||||||
+76
@@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.springframework.context.annotation.Profile;
|
import org.springframework.context.annotation.Profile;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@@ -105,6 +106,81 @@ public class TestCleanupInternalController {
|
|||||||
return ResponseEntity.ok(body);
|
return ResponseEntity.ok(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Playwright 실행 전 동일 이메일 계정의 존재 여부를 확인한다. 조회 전용이며 삭제하지 않는다.
|
||||||
|
*/
|
||||||
|
@GetMapping("/user/exists")
|
||||||
|
public ResponseEntity<Map<String, Object>> checkUserExists(
|
||||||
|
@RequestParam String email, HttpServletRequest request) {
|
||||||
|
ResponseEntity<Map<String, Object>> guardFailure = checkGuards(request);
|
||||||
|
if (guardFailure != null) {
|
||||||
|
return guardFailure;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(email)) {
|
||||||
|
return badRequest("email 은 필수입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCleanupResult result = testCleanupService.checkUserExists(email);
|
||||||
|
log.info("테스트 정리(user exists) 조회 - email: {}, found: {}, from: {}",
|
||||||
|
email, result.isFound(), request.getRemoteAddr());
|
||||||
|
|
||||||
|
Map<String, Object> body = baseBody();
|
||||||
|
body.put("email", email);
|
||||||
|
body.put("userId", result.getTargetId());
|
||||||
|
body.put("userFound", result.isFound());
|
||||||
|
return ResponseEntity.ok(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰 번호로 남아 있는 초대 레코드를 삭제한다. 1020 재실행 전 초대중 중복을 정리하는 용도다.
|
||||||
|
*/
|
||||||
|
@PostMapping("/invitation")
|
||||||
|
public ResponseEntity<Map<String, Object>> deleteInvitations(
|
||||||
|
@RequestParam String mobile, HttpServletRequest request) {
|
||||||
|
ResponseEntity<Map<String, Object>> guardFailure = checkGuards(request);
|
||||||
|
if (guardFailure != null) {
|
||||||
|
return guardFailure;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(mobile)) {
|
||||||
|
return badRequest("mobile 은 필수입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCleanupResult result = testCleanupService.deleteInvitationsByMobile(mobile);
|
||||||
|
log.info("테스트 정리(invitation) 실행 - mobile: {}, found: {}, from: {}",
|
||||||
|
mobile, result.isFound(), request.getRemoteAddr());
|
||||||
|
|
||||||
|
Map<String, Object> body = baseBody();
|
||||||
|
body.put("mobile", mobile);
|
||||||
|
body.put("invitationFound", result.isFound());
|
||||||
|
body.put("deletedCounts", result.getDeletedCounts());
|
||||||
|
return ResponseEntity.ok(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰 번호로 찾은 계정을 법인 소속에서 제외한다. 계정 자체는 삭제하지 않는다.
|
||||||
|
*/
|
||||||
|
@PostMapping("/membership")
|
||||||
|
public ResponseEntity<Map<String, Object>> detachMembership(
|
||||||
|
@RequestParam String mobile, HttpServletRequest request) {
|
||||||
|
ResponseEntity<Map<String, Object>> guardFailure = checkGuards(request);
|
||||||
|
if (guardFailure != null) {
|
||||||
|
return guardFailure;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(mobile)) {
|
||||||
|
return badRequest("mobile 은 필수입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCleanupResult result = testCleanupService.detachUsersFromOrgByMobile(mobile);
|
||||||
|
log.info("테스트 정리(membership) 실행 - mobile: {}, found: {}, from: {}",
|
||||||
|
mobile, result.isFound(), request.getRemoteAddr());
|
||||||
|
|
||||||
|
Map<String, Object> body = baseBody();
|
||||||
|
body.put("mobile", mobile);
|
||||||
|
body.put("membershipFound", result.isFound());
|
||||||
|
body.put("deletedCounts", result.getDeletedCounts());
|
||||||
|
return ResponseEntity.ok(body);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/orphans")
|
@PostMapping("/orphans")
|
||||||
public ResponseEntity<Map<String, Object>> cleanOrphans(HttpServletRequest request) {
|
public ResponseEntity<Map<String, Object>> cleanOrphans(HttpServletRequest request) {
|
||||||
ResponseEntity<Map<String, Object>> guardFailure = checkGuards(request);
|
ResponseEntity<Map<String, Object>> guardFailure = checkGuards(request);
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestEventReposit
|
|||||||
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestRepository;
|
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestRepository;
|
||||||
import com.eactive.apim.portal.djb.webhook.repository.entity.WebhookRequest;
|
import com.eactive.apim.portal.djb.webhook.repository.entity.WebhookRequest;
|
||||||
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
||||||
|
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||||
|
import com.eactive.apim.portal.invitation.repository.UserInvitationRepository;
|
||||||
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||||
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
||||||
|
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums.RoleCode;
|
||||||
import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementRepository;
|
import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementRepository;
|
||||||
import com.eactive.apim.portal.portaluser.repository.PortalUserRepository;
|
import com.eactive.apim.portal.portaluser.repository.PortalUserRepository;
|
||||||
import com.eactive.apim.portal.portaluser.repository.UserPasswordHistoryRepository;
|
import com.eactive.apim.portal.portaluser.repository.UserPasswordHistoryRepository;
|
||||||
@@ -57,6 +60,7 @@ public class TestCleanupService {
|
|||||||
private final WebhookRequestApiRepository webhookRequestApiRepository;
|
private final WebhookRequestApiRepository webhookRequestApiRepository;
|
||||||
private final WebhookRequestEventRepository webhookRequestEventRepository;
|
private final WebhookRequestEventRepository webhookRequestEventRepository;
|
||||||
private final WebhookService webhookService;
|
private final WebhookService webhookService;
|
||||||
|
private final UserInvitationRepository userInvitationRepository;
|
||||||
private final TestCleanupNativeQueries nativeQueries;
|
private final TestCleanupNativeQueries nativeQueries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,6 +70,12 @@ public class TestCleanupService {
|
|||||||
assertNonProdProfile();
|
assertNonProdProfile();
|
||||||
|
|
||||||
Optional<PortalOrg> orgOpt = portalOrgRepository.findByCompRegNo(compRegNo);
|
Optional<PortalOrg> orgOpt = portalOrgRepository.findByCompRegNo(compRegNo);
|
||||||
|
// 가입 화면은 000-00-00001처럼 입력받지만 DB에는 숫자만 저장되는 환경도 있다.
|
||||||
|
// cleanup API는 두 형식을 모두 받아 이전 E2E 실행 법인을 빠짐없이 정리해야 한다.
|
||||||
|
String digitsOnlyCompRegNo = compRegNo.replaceAll("\\D", "");
|
||||||
|
if (!orgOpt.isPresent() && !digitsOnlyCompRegNo.isEmpty() && !digitsOnlyCompRegNo.equals(compRegNo)) {
|
||||||
|
orgOpt = portalOrgRepository.findByCompRegNo(digitsOnlyCompRegNo);
|
||||||
|
}
|
||||||
if (!orgOpt.isPresent()) {
|
if (!orgOpt.isPresent()) {
|
||||||
return TestCleanupResult.notFound();
|
return TestCleanupResult.notFound();
|
||||||
}
|
}
|
||||||
@@ -73,6 +83,8 @@ public class TestCleanupService {
|
|||||||
String orgId = org.getId();
|
String orgId = org.getId();
|
||||||
TestCleanupResult result = TestCleanupResult.found(orgId);
|
TestCleanupResult result = TestCleanupResult.found(orgId);
|
||||||
|
|
||||||
|
result.put("PTL_USER_INVITATION", userInvitationRepository.deleteByOrgId(orgId));
|
||||||
|
|
||||||
List<PortalUser> users = portalUserRepository.findAllByPortalOrg_Id(orgId);
|
List<PortalUser> users = portalUserRepository.findAllByPortalOrg_Id(orgId);
|
||||||
for (PortalUser user : users) {
|
for (PortalUser user : users) {
|
||||||
result.merge(deleteUserCascadeInternal(user));
|
result.merge(deleteUserCascadeInternal(user));
|
||||||
@@ -118,6 +130,60 @@ public class TestCleanupService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 이메일 기준으로 테스트 계정 존재 여부만 조회한다. 삭제나 데이터 변경은 수행하지 않는다.
|
||||||
|
*/
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public TestCleanupResult checkUserExists(String email) {
|
||||||
|
assertNonProdProfile();
|
||||||
|
|
||||||
|
return portalUserRepository.findPortalUserByEmailAddr(email)
|
||||||
|
.map(user -> TestCleanupResult.found(user.getId()))
|
||||||
|
.orElseGet(TestCleanupResult::notFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰 번호로 남은 초대 레코드를 전부 삭제한다. 1020 재실행 전 PENDING 초대 중복을 방지한다.
|
||||||
|
*/
|
||||||
|
public TestCleanupResult deleteInvitationsByMobile(String mobile) {
|
||||||
|
assertNonProdProfile();
|
||||||
|
|
||||||
|
String normalizedMobile = PhoneNumberUtil.normalize(mobile);
|
||||||
|
if (normalizedMobile == null) {
|
||||||
|
return TestCleanupResult.notFound();
|
||||||
|
}
|
||||||
|
long deleted = userInvitationRepository.deleteByInvitationMobile(normalizedMobile);
|
||||||
|
TestCleanupResult result = deleted > 0 ? TestCleanupResult.found(normalizedMobile) : TestCleanupResult.notFound();
|
||||||
|
result.put("PTL_USER_INVITATION", deleted);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰 번호로 찾은 계정을 법인 소속에서만 제외해 개인회원으로 되돌린다.
|
||||||
|
* 1020이 수락/소속 제외 전에 중단된 경우, 1000 선행 개인회원은 보존하면서 재초대 가능 상태로 복구한다.
|
||||||
|
*/
|
||||||
|
public TestCleanupResult detachUsersFromOrgByMobile(String mobile) {
|
||||||
|
assertNonProdProfile();
|
||||||
|
|
||||||
|
String normalizedMobile = PhoneNumberUtil.normalize(mobile);
|
||||||
|
if (normalizedMobile == null) {
|
||||||
|
return TestCleanupResult.notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCleanupResult result = TestCleanupResult.notFound();
|
||||||
|
for (PortalUser user : portalUserRepository.findAllByMobileNumber(normalizedMobile)) {
|
||||||
|
if (user.getPortalOrg() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
user.setPortalOrg(null);
|
||||||
|
user.setRoleCode(RoleCode.ROLE_USER);
|
||||||
|
portalUserRepository.save(user);
|
||||||
|
result = TestCleanupResult.found(user.getId());
|
||||||
|
result.put("PTL_USER_ORG_MEMBERSHIP", 1L);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private TestCleanupResult deleteUserCascadeInternal(PortalUser user) {
|
private TestCleanupResult deleteUserCascadeInternal(PortalUser user) {
|
||||||
TestCleanupResult result = TestCleanupResult.found(user.getId());
|
TestCleanupResult result = TestCleanupResult.found(user.getId());
|
||||||
result.put("PTL_INQUIRY_COMMENT", inquiryCommentRepository.deleteByInquiry_Inquirer_Id(user.getId()));
|
result.put("PTL_INQUIRY_COMMENT", inquiryCommentRepository.deleteByInquiry_Inquirer_Id(user.getId()));
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.eactive.apim.portal.apps.user;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.apps.user.service.PasswordService;
|
||||||
|
import com.eactive.apim.portal.common.dto.PasswordValidationDTO;
|
||||||
|
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
||||||
|
import com.eactive.apim.portal.portaluser.entity.UserPasswordHistory;
|
||||||
|
import com.eactive.apim.portal.portaluser.repository.PortalUserRepository;
|
||||||
|
import com.eactive.apim.portal.portaluser.repository.UserPasswordHistoryRepository;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class PasswordServiceTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PortalUserRepository portalUserRepository;
|
||||||
|
@Mock
|
||||||
|
private UserPasswordHistoryRepository passwordHistoryRepository;
|
||||||
|
@Mock
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
@Mock
|
||||||
|
private LocalValidatorFactoryBean validator;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private PasswordService passwordService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsPasswordStoredAgainstPortalUserId() {
|
||||||
|
PortalUser user = new PortalUser();
|
||||||
|
user.setId("user-uuid");
|
||||||
|
user.setLoginId("user@example.com");
|
||||||
|
user.setMobileNumber("010-1234-5678");
|
||||||
|
user.setPasswordHash("temporary-password-hash");
|
||||||
|
|
||||||
|
UserPasswordHistory previousPassword = new UserPasswordHistory();
|
||||||
|
previousPassword.setUserId("user-uuid");
|
||||||
|
previousPassword.setPasswordHash("original-password-hash");
|
||||||
|
|
||||||
|
when(portalUserRepository.findByLoginId("user@example.com")).thenReturn(Optional.of(user));
|
||||||
|
when(passwordEncoder.matches("Original!123", "temporary-password-hash")).thenReturn(false);
|
||||||
|
when(validator.validate(any(PasswordValidationDTO.class))).thenReturn(Collections.emptySet());
|
||||||
|
when(passwordHistoryRepository.findRecentPasswordsByUserId("user-uuid"))
|
||||||
|
.thenReturn(Collections.singletonList(previousPassword));
|
||||||
|
when(passwordEncoder.matches("Original!123", "original-password-hash")).thenReturn(true);
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() -> passwordService.updatePassword(
|
||||||
|
"user@example.com", "Original!123", "Original!123")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals("최근 5회 이내에 사용한 비밀번호는 사용할 수 없습니다.", exception.getMessage());
|
||||||
|
verify(passwordHistoryRepository).findRecentPasswordsByUserId("user-uuid");
|
||||||
|
verify(passwordHistoryRepository, never()).findRecentPasswordsByUserId("user@example.com");
|
||||||
|
verify(portalUserRepository, never()).save(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
+74
-1
@@ -2,6 +2,7 @@ package com.eactive.apim.portal.djb.testcleanup.service;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
@@ -22,6 +23,7 @@ import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestEventReposit
|
|||||||
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestRepository;
|
import com.eactive.apim.portal.djb.webhook.repository.WebhookRequestRepository;
|
||||||
import com.eactive.apim.portal.djb.webhook.repository.entity.WebhookRequest;
|
import com.eactive.apim.portal.djb.webhook.repository.entity.WebhookRequest;
|
||||||
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
import com.eactive.apim.portal.djb.webhook.service.WebhookService;
|
||||||
|
import com.eactive.apim.portal.invitation.repository.UserInvitationRepository;
|
||||||
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||||
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
||||||
import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementRepository;
|
import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementRepository;
|
||||||
@@ -60,6 +62,7 @@ class TestCleanupServiceTest {
|
|||||||
@Mock private WebhookRequestApiRepository webhookRequestApiRepository;
|
@Mock private WebhookRequestApiRepository webhookRequestApiRepository;
|
||||||
@Mock private WebhookRequestEventRepository webhookRequestEventRepository;
|
@Mock private WebhookRequestEventRepository webhookRequestEventRepository;
|
||||||
@Mock private WebhookService webhookService;
|
@Mock private WebhookService webhookService;
|
||||||
|
@Mock private UserInvitationRepository userInvitationRepository;
|
||||||
@Mock private TestCleanupNativeQueries nativeQueries;
|
@Mock private TestCleanupNativeQueries nativeQueries;
|
||||||
|
|
||||||
private TestCleanupService service;
|
private TestCleanupService service;
|
||||||
@@ -76,7 +79,7 @@ class TestCleanupServiceTest {
|
|||||||
inquiryRepository, inquiryCommentRepository, partnershipApplicationRepository,
|
inquiryRepository, inquiryCommentRepository, partnershipApplicationRepository,
|
||||||
userRoleHistoryRepository, portalUserPrivacyAgreementRepository, userPasswordHistoryRepository,
|
userRoleHistoryRepository, portalUserPrivacyAgreementRepository, userPasswordHistoryRepository,
|
||||||
userLogRepository, credentialRepository, webhookRequestRepository, webhookRequestApiRepository,
|
userLogRepository, credentialRepository, webhookRequestRepository, webhookRequestApiRepository,
|
||||||
webhookRequestEventRepository, webhookService, nativeQueries);
|
webhookRequestEventRepository, webhookService, userInvitationRepository, nativeQueries);
|
||||||
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(false);
|
when(environment.acceptsProfiles(Profiles.of("stage", "prod"))).thenReturn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +101,24 @@ class TestCleanupServiceTest {
|
|||||||
verifyNoInteractions(webhookService, portalUserRepository);
|
verifyNoInteractions(webhookService, portalUserRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteOrgCascade_fallsBackToDigitsOnlyBusinessNumber() {
|
||||||
|
String hyphenatedCompRegNo = "123-45-67890";
|
||||||
|
String digitsOnlyCompRegNo = "1234567890";
|
||||||
|
PortalOrg org = org();
|
||||||
|
when(portalOrgRepository.findByCompRegNo(hyphenatedCompRegNo)).thenReturn(Optional.empty());
|
||||||
|
when(portalOrgRepository.findByCompRegNo(digitsOnlyCompRegNo)).thenReturn(Optional.of(org));
|
||||||
|
when(portalUserRepository.findAllByPortalOrg_Id(ORG_ID)).thenReturn(Collections.emptyList());
|
||||||
|
when(webhookRequestRepository.findByOrgId(ORG_ID)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
TestCleanupResult result = service.deleteOrgCascade(hyphenatedCompRegNo);
|
||||||
|
|
||||||
|
assertTrue(result.isFound());
|
||||||
|
assertEquals(ORG_ID, result.getTargetId());
|
||||||
|
verify(portalOrgRepository).findByCompRegNo(digitsOnlyCompRegNo);
|
||||||
|
verify(portalOrgRepository).delete(org);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void deleteOrgCascade_found_cascadesUsersAndOrg() {
|
void deleteOrgCascade_found_cascadesUsersAndOrg() {
|
||||||
PortalOrg org = org();
|
PortalOrg org = org();
|
||||||
@@ -153,6 +174,58 @@ class TestCleanupServiceTest {
|
|||||||
assertTrue(result.getDeletedCounts().isEmpty());
|
assertTrue(result.getDeletedCounts().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void checkUserExists_found_doesNotDeleteData() {
|
||||||
|
when(portalUserRepository.findPortalUserByEmailAddr(EMAIL)).thenReturn(Optional.of(user()));
|
||||||
|
|
||||||
|
TestCleanupResult result = service.checkUserExists(EMAIL);
|
||||||
|
|
||||||
|
assertTrue(result.isFound());
|
||||||
|
assertEquals(USER_ID, result.getTargetId());
|
||||||
|
assertTrue(result.getDeletedCounts().isEmpty());
|
||||||
|
verify(portalUserRepository, never()).delete(org.mockito.ArgumentMatchers.any(PortalUser.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void checkUserExists_notFound() {
|
||||||
|
when(portalUserRepository.findPortalUserByEmailAddr(EMAIL)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
TestCleanupResult result = service.checkUserExists(EMAIL);
|
||||||
|
|
||||||
|
assertFalse(result.isFound());
|
||||||
|
assertTrue(result.getDeletedCounts().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deleteInvitationsByMobile_normalizesAndDeletesAllMatches() {
|
||||||
|
when(userInvitationRepository.deleteByInvitationMobile("010-1234-5678")).thenReturn(2L);
|
||||||
|
|
||||||
|
TestCleanupResult result = service.deleteInvitationsByMobile("01012345678");
|
||||||
|
|
||||||
|
assertTrue(result.isFound());
|
||||||
|
assertEquals("010-1234-5678", result.getTargetId());
|
||||||
|
assertEquals(2L, result.getDeletedCounts().get("PTL_USER_INVITATION"));
|
||||||
|
verify(userInvitationRepository).deleteByInvitationMobile("010-1234-5678");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void detachUsersFromOrgByMobile_keepsUserAndRemovesOnlyMembership() {
|
||||||
|
PortalUser target = user();
|
||||||
|
target.setPortalOrg(org());
|
||||||
|
when(portalUserRepository.findAllByMobileNumber("010-1234-5678"))
|
||||||
|
.thenReturn(Collections.singletonList(target));
|
||||||
|
|
||||||
|
TestCleanupResult result = service.detachUsersFromOrgByMobile("01012345678");
|
||||||
|
|
||||||
|
assertTrue(result.isFound());
|
||||||
|
assertEquals(USER_ID, result.getTargetId());
|
||||||
|
assertEquals(1L, result.getDeletedCounts().get("PTL_USER_ORG_MEMBERSHIP"));
|
||||||
|
assertNull(target.getPortalOrg());
|
||||||
|
assertEquals(com.eactive.apim.portal.portaluser.entity.PortalUserEnums.RoleCode.ROLE_USER, target.getRoleCode());
|
||||||
|
verify(portalUserRepository).save(target);
|
||||||
|
verify(portalUserRepository, never()).delete(target);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void deleteUserCascade_found_deletesOrphanDataAndUser() {
|
void deleteUserCascade_found_deletesOrphanDataAndUser() {
|
||||||
PortalUser target = user();
|
PortalUser target = user();
|
||||||
|
|||||||
Reference in New Issue
Block a user