diff --git a/pre-registration-booking-service/pom.xml b/pre-registration-booking-service/pom.xml index 948569ade72..0f714ba5f2d 100644 --- a/pre-registration-booking-service/pom.xml +++ b/pre-registration-booking-service/pom.xml @@ -14,6 +14,7 @@ UTF-8 1.4.2 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT 1.4.0-SNAPSHOT 1.4.0-SNAPSHOT 21 @@ -143,6 +144,11 @@ pre-registration-core ${pre.registration.core.version} + + io.mosip.preregistration + pre-registration-application-service + ${pre.registration.application.service.version} + io.mosip.kernel kernel-core diff --git a/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/BookingService.java b/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/BookingService.java index c4ac2fe0a94..3b8c2072cac 100644 --- a/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/BookingService.java +++ b/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/BookingService.java @@ -45,6 +45,7 @@ import io.mosip.preregistration.booking.exception.RecordNotFoundException; import io.mosip.preregistration.booking.exception.util.BookingExceptionCatcher; import io.mosip.preregistration.booking.repository.impl.BookingDAO; +import io.mosip.preregistration.application.service.ApplicationIdentityMigrationService; import io.mosip.preregistration.booking.service.util.BookingLock; import io.mosip.preregistration.booking.service.util.BookingServiceUtil; import io.mosip.preregistration.core.code.AuditLogVariables; @@ -83,6 +84,9 @@ public class BookingService implements BookingServiceIntf { @Autowired BookingServiceUtil serviceUtil; + @Autowired + private ApplicationIdentityMigrationService applicationIdentityMigrationService; + /** * Reference for ${preregistration.availability.sync} from property file */ @@ -641,8 +645,9 @@ public BookingStatusDTO book(String preRegistrationId, BookingRequestDTO booking " and Date and Time " + availableEntity.getRegDate() + " " + availableEntity.getFromTime()); if (serviceUtil.isKiosksAvailable(availableEntity)) { /* Updating booking */ - bookingDAO.saveRegistrationEntityForBooking( + RegistrationBookingEntity bookingEntity = bookingDAO.saveRegistrationEntityForBooking( serviceUtil.bookingEntitySetter(preRegistrationId, bookingRequestDTO)); + applicationIdentityMigrationService.migrateRawUserToEffectiveUser(preRegistrationId, bookingEntity.getCrBy()); /* Reduce Availability */ availableEntity.setAvailableKiosks(availableEntity.getAvailableKiosks() - 1); AvailibityEntity availableUpdate = bookingDAO.updateAvailibityEntity(availableEntity); @@ -704,6 +709,10 @@ public CancelBookingResponseDTO cancelBooking(String preRegistrationId, boolean serviceUtil.timeSpanCheckForCancle(bookedDateTime); } + String effectiveUserId = applicationIdentityMigrationService + .resolveEffectiveUserId(bookingEntity.getCrBy()); + applicationIdentityMigrationService.migrateRawUserToEffectiveUser(preRegistrationId, + effectiveUserId); /* Deleting the canceled booking */ // bookingDAO.deleteRegistrationEntity(bookingEntity); bookingDAO.deleteByPreRegistrationId(preRegistrationId); @@ -765,6 +774,9 @@ public MainResponseDTO deleteBooking(String preregId) { if (validationUtil.requstParamValidator(requestParamMap) && serviceUtil.checkApplicationStatus(preregId)) { RegistrationBookingEntity registrationEntityList = bookingDAO.findByPreRegistrationId(preregId); + String effectiveUserId = applicationIdentityMigrationService + .resolveEffectiveUserId(registrationEntityList.getCrBy()); + applicationIdentityMigrationService.migrateRawUserToEffectiveUser(preregId, effectiveUserId); String str = registrationEntityList.getRegDate() + " " + registrationEntityList.getSlotFromTime(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); LocalDateTime bookedDateTime = LocalDateTime.parse(str, formatter); @@ -782,7 +794,7 @@ public MainResponseDTO deleteBooking(String preregId) { bookingDAO.updateAvailibityEntity(availableEntity); deleteDto.setPreRegistrationId(registrationEntityList.getPreregistrationId()); - deleteDto.setDeletedBy(registrationEntityList.getCrBy()); + deleteDto.setDeletedBy(effectiveUserId); deleteDto.setDeletedDateTime(new Date(System.currentTimeMillis())); } diff --git a/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/util/BookingServiceUtil.java b/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/util/BookingServiceUtil.java index 2090c2d9346..96ba3a81822 100644 --- a/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/util/BookingServiceUtil.java +++ b/pre-registration-booking-service/src/main/java/io/mosip/preregistration/booking/service/util/BookingServiceUtil.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; +import java.util.UUID; import jakarta.annotation.PostConstruct; @@ -69,6 +70,7 @@ import io.mosip.preregistration.booking.exception.BookingPreIdNotFoundException; import io.mosip.preregistration.booking.exception.BookingRegistrationCenterIdNotFoundException; import io.mosip.preregistration.booking.exception.BookingTimeSlotNotSeletectedException; +import io.mosip.preregistration.booking.exception.AppointmentBookingFailedException; import io.mosip.preregistration.booking.exception.DemographicGetStatusException; import io.mosip.preregistration.booking.exception.InvalidDateTimeFormatException; import io.mosip.preregistration.booking.exception.RecordNotFoundException; @@ -81,12 +83,16 @@ import io.mosip.preregistration.core.common.dto.RequestWrapper; import io.mosip.preregistration.core.common.dto.ResponseWrapper; import io.mosip.preregistration.core.common.entity.RegistrationBookingEntity; +import io.mosip.preregistration.core.common.entity.UserDetails; import io.mosip.preregistration.core.config.LoggerConfiguration; import io.mosip.preregistration.core.exception.MasterDataNotAvailableException; import io.mosip.preregistration.core.exception.NotificationException; import io.mosip.preregistration.core.exception.RestCallException; import io.mosip.preregistration.core.util.UUIDGeneratorUtil; import io.mosip.preregistration.core.util.ValidationUtil; +import io.mosip.preregistration.core.common.service.UserDetailsService; +import io.mosip.preregistration.core.exception.UserLookupException; +import io.mosip.preregistration.core.util.GenericUtil; /** * This class provides the utility methods for Booking application. @@ -107,6 +113,9 @@ public class BookingServiceUtil { @Autowired private RestTemplate restTemplate; + @Autowired + private UserDetailsService userDetailsService; + /** * Reference for ${regCenter.url} from property file */ @@ -140,6 +149,9 @@ public class BookingServiceUtil { @Value("${mosip.notification.timezone}") private String specificZoneId; + @Value("${mosip.prereg.pii.backward.compatibility}") + private boolean piiBackwardCompatibility; + /** * ObjectMapper global object creation */ @@ -535,7 +547,8 @@ public RegistrationBookingEntity bookingEntitySetter(String preRegistrationId, entity.setRegistrationCenterId(bookingRequestDTO.getRegistrationCenterId()); entity.setId(UUIDGeneratorUtil.generateId()); entity.setLangCode("12L"); - entity.setCrBy(authUserDetails().getUserId()); + String userId = authUserDetails().getUserId(); + entity.setCrBy(resolveEffectiveCrBy(userId)); entity.setCrDate(DateUtils2.parseDateToLocalDateTime(new Date())); entity.setRegDate(LocalDate.parse(bookingRequestDTO.getRegDate())); entity.setSlotFromTime(LocalTime.parse(bookingRequestDTO.getSlotFromTime())); @@ -544,6 +557,24 @@ public RegistrationBookingEntity bookingEntitySetter(String preRegistrationId, return entity; } + private String resolveEffectiveCrBy(String userId) { + String maskedUserId = GenericUtil.maskIdentifier(userId); + try { + String effectiveCrBy = userDetailsService.getOrCreateInternalUserId(userId); + boolean canonicalApplied = effectiveCrBy != null && !effectiveCrBy.isBlank() + && !effectiveCrBy.trim().equals(userId == null ? "" : userId.trim()); + log.info("sessionId", "idType", "id", + "Resolved effective user id for booking write. maskedUserId=" + maskedUserId + + ", canonicalApplied=" + canonicalApplied); + return effectiveCrBy; + } catch (UserLookupException ex) { + log.warn("sessionId", "idType", "id", + "Failed to resolve effective booking user id for " + maskedUserId); + throw new AppointmentBookingFailedException(ErrorCodes.PRG_BOOK_RCI_005.getCode(), + ErrorMessages.APPOINTMENT_BOOKING_FAILED.getMessage()); + } + } + /** * * @param notificationDTO @@ -734,3 +765,4 @@ public MainResponseDTO getApplicationStatus(String applicationId) { // } } + diff --git a/pre-registration-booking-service/src/main/resources/bootstrap.properties b/pre-registration-booking-service/src/main/resources/bootstrap.properties index 46f53f8cdac..54351b9d9a4 100644 --- a/pre-registration-booking-service/src/main/resources/bootstrap.properties +++ b/pre-registration-booking-service/src/main/resources/bootstrap.properties @@ -15,6 +15,7 @@ server.port=9095 health.config.enabled=false mosip.preregistration.booking.id.book=mosip.pre-registration.booking.book mosip.id.preregistration.booking.book=mosip.pre-registration.booking.book +mosip.prereg.pii.backward.compatibility=false #disabling health check so that client doesnt try to load properties from sprint config server every # 5 minutes (should not be done in production) diff --git a/pre-registration-booking-service/src/test/java/io/mosip/preregistration/booking/test/service/util/BookingServiceUtilTest.java b/pre-registration-booking-service/src/test/java/io/mosip/preregistration/booking/test/service/util/BookingServiceUtilTest.java index 4b15de71e79..31c72ac39ff 100644 --- a/pre-registration-booking-service/src/test/java/io/mosip/preregistration/booking/test/service/util/BookingServiceUtilTest.java +++ b/pre-registration-booking-service/src/test/java/io/mosip/preregistration/booking/test/service/util/BookingServiceUtilTest.java @@ -13,7 +13,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - +import io.mosip.preregistration.booking.exception.*; +import io.mosip.preregistration.core.exception.UserLookupException; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -32,6 +33,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -51,15 +53,6 @@ import io.mosip.preregistration.booking.dto.RegistrationCenterResponseDto; import io.mosip.preregistration.booking.dto.SlotDto; import io.mosip.preregistration.booking.entity.AvailibityEntity; -import io.mosip.preregistration.booking.exception.AppointmentReBookingFailedException; -import io.mosip.preregistration.booking.exception.AvailablityNotFoundException; -import io.mosip.preregistration.booking.exception.BookingDateNotSeletectedException; -import io.mosip.preregistration.booking.exception.BookingPreIdNotFoundException; -import io.mosip.preregistration.booking.exception.BookingRegistrationCenterIdNotFoundException; -import io.mosip.preregistration.booking.exception.BookingTimeSlotNotSeletectedException; -import io.mosip.preregistration.booking.exception.InvalidDateTimeFormatException; -import io.mosip.preregistration.booking.exception.RecordNotFoundException; -import io.mosip.preregistration.booking.exception.TimeSpanException; import io.mosip.preregistration.booking.repository.BookingAvailabilityRepository; import io.mosip.preregistration.booking.repository.RegistrationBookingRepository; import io.mosip.preregistration.booking.repository.impl.BookingDAO; @@ -68,6 +61,8 @@ import io.mosip.preregistration.core.common.dto.MainRequestDTO; import io.mosip.preregistration.core.common.dto.NotificationDTO; import io.mosip.preregistration.core.common.dto.ResponseWrapper; +import io.mosip.preregistration.core.common.entity.RegistrationBookingEntity; +import io.mosip.preregistration.core.common.service.UserDetailsService; import io.mosip.preregistration.core.exception.MasterDataNotAvailableException; import io.mosip.preregistration.core.exception.RestCallException; import io.mosip.preregistration.core.util.RequestValidator; @@ -97,6 +92,9 @@ public class BookingServiceUtilTest { @MockBean private BookingDAO bookingDAO; + @MockBean + private UserDetailsService userDetailsService; + @Mock private AuthUserDetails authUserDetails; @@ -139,6 +137,9 @@ public void setup() throws Exception { Mockito.when(securityContext.getAuthentication()).thenReturn(authentication); SecurityContextHolder.setContext(securityContext); Mockito.when(SecurityContextHolder.getContext().getAuthentication().getPrincipal()).thenReturn(applicationUser); + Mockito.when(applicationUser.getUserId()).thenReturn("test-user"); + Mockito.when(userDetailsService.getOrCreateInternalUserId("test-user")) + .thenReturn("00000000-0000-0000-0000-000000000001"); centerDto.setId("10001"); centerDto.setLangCode("eng"); centerDto.setCenterStartTime(startTime); @@ -568,6 +569,44 @@ public void emailNotificationTest() throws JsonProcessingException { @Test public void bookingEntitySetterTest() { + ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", false); + BookingRequestDTO bookingRequestDTO = new BookingRequestDTO(); + bookingRequestDTO.setRegistrationCenterId("1"); + bookingRequestDTO.setSlotFromTime("09:00"); + bookingRequestDTO.setSlotToTime("09:13"); + bookingRequestDTO.setRegDate("2018-12-06"); + serviceUtil.bookingEntitySetter("1234568687844744", bookingRequestDTO); + } + + @Test + public void bookingEntitySetterLegacyCrByTest() { + ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", false); + BookingRequestDTO bookingRequestDTO = new BookingRequestDTO(); + bookingRequestDTO.setRegistrationCenterId("1"); + bookingRequestDTO.setSlotFromTime("09:00"); + bookingRequestDTO.setSlotToTime("09:13"); + bookingRequestDTO.setRegDate("2018-12-06"); + RegistrationBookingEntity entity = serviceUtil.bookingEntitySetter("1234568687844744", bookingRequestDTO); + assertEquals("00000000-0000-0000-0000-000000000001", entity.getCrBy()); + } + + @Test + public void bookingEntitySetterWithCompatibilityModeWritesUuidTest() { + ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", true); + BookingRequestDTO bookingRequestDTO = new BookingRequestDTO(); + bookingRequestDTO.setRegistrationCenterId("1"); + bookingRequestDTO.setSlotFromTime("09:00"); + bookingRequestDTO.setSlotToTime("09:13"); + bookingRequestDTO.setRegDate("2018-12-06"); + RegistrationBookingEntity entity = serviceUtil.bookingEntitySetter("1234568687844744", bookingRequestDTO); + assertEquals("00000000-0000-0000-0000-000000000001", entity.getCrBy()); + } + + @Test(expected = AppointmentBookingFailedException.class) + public void bookingEntitySetterThrowsOnUuidResolutionFailureTest() { + ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", false); + Mockito.when(userDetailsService.getOrCreateInternalUserId("test-user")) + .thenThrow(new UserLookupException("PRG_CORE_REQ_024", "Failed to resolve internal user ID")); BookingRequestDTO bookingRequestDTO = new BookingRequestDTO(); bookingRequestDTO.setRegistrationCenterId("1"); bookingRequestDTO.setSlotFromTime("09:00"); @@ -646,3 +685,5 @@ public void timeSpanCheckForRebook1() { } } + + diff --git a/pre-registration-booking-service/src/test/resources/application.properties b/pre-registration-booking-service/src/test/resources/application.properties index 4c5991c7926..ad94dc47102 100644 --- a/pre-registration-booking-service/src/test/resources/application.properties +++ b/pre-registration-booking-service/src/test/resources/application.properties @@ -26,6 +26,7 @@ preregistration.rebook.timespan = 24 preregistration.cancel.timespan = 24 preregistration.timespan.cancel=24 preregistration.timespan.rebook=24 +mosip.prereg.pii.backward.compatibility=false service.version=v1.0 master.service.env=masterdata