Skip to content
Draft
4 changes: 2 additions & 2 deletions pre-registration-booking-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<io.micrometer.prometheus.version>1.4.2</io.micrometer.prometheus.version>
<pre.registration.core.version>1.2.1-SNAPSHOT</pre.registration.core.version>
<kernel.core.version>1.2.1-SNAPSHOT</kernel.core.version>
<kernel.bom.version>1.2.1-SNAPSHOT</kernel.bom.version>
<kernel.core.version>1.3.0</kernel.core.version>
<kernel.bom.version>1.3.0</kernel.bom.version>
<java.version>21</java.version>
<!-- Core -->
<spring.boot.version>3.2.3</spring.boot.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;

import jakarta.annotation.PostConstruct;

Expand Down Expand Up @@ -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;
Expand All @@ -81,12 +83,14 @@
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;

/**
* This class provides the utility methods for Booking application.
Expand All @@ -107,6 +111,9 @@ public class BookingServiceUtil {
@Autowired
private RestTemplate restTemplate;

@Autowired
private UserDetailsService userDetailsService;

/**
* Reference for ${regCenter.url} from property file
*/
Expand Down Expand Up @@ -140,6 +147,9 @@ public class BookingServiceUtil {
@Value("${mosip.notification.timezone}")
private String specificZoneId;

@Value("${mosip.prereg.pii.backward.compatibility:false}")
private boolean piiBackwardCompatibility;

/**
* ObjectMapper global object creation
*/
Expand Down Expand Up @@ -535,7 +545,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(DateUtils.parseDateToLocalDateTime(new Date()));
entity.setRegDate(LocalDate.parse(bookingRequestDTO.getRegDate()));
entity.setSlotFromTime(LocalTime.parse(bookingRequestDTO.getSlotFromTime()));
Expand All @@ -544,6 +555,55 @@ public RegistrationBookingEntity bookingEntitySetter(String preRegistrationId,
return entity;
}

private String resolveEffectiveCrBy(String userId) {
try {
UserDetails userDetail = userDetailsService.findOrCreateByIdentifier(userId);
if (userDetail != null && userDetail.getUserId() != null) {
return userDetail.getUserId().toString();
}
} catch (Exception ex) {
log.warn("sessionId", "idType", "id",
"Failed to resolve canonical user id for booking: " + maskIdentifier(userId));
}
if (piiBackwardCompatibility) {
log.warn("sessionId", "idType", "id",
"Falling back to raw identifier for booking due to backward-compatibility mode");
return userId;
}
throw new AppointmentBookingFailedException(ErrorCodes.PRG_BOOK_RCI_005.getCode(),
ErrorMessages.APPOINTMENT_BOOKING_FAILED.getMessage());
}

private String maskIdentifier(String value) {
if (value == null || value.isBlank()) {
return "<empty>";
}
String trimmed = value.trim();
int atIndex = trimmed.indexOf('@');
if (atIndex > 0 && atIndex < trimmed.length() - 1) {
String local = trimmed.substring(0, atIndex);
String domain = trimmed.substring(atIndex);
String visibleLocal = local.substring(0, 1);
return visibleLocal + "***" + domain;
}
if (trimmed.matches("\\+?\\d{10,12}")) {
boolean hasPlus = trimmed.startsWith("+");
String digits = hasPlus ? trimmed.substring(1) : trimmed;
if (digits.length() <= 4) {
return (hasPlus ? "+" : "") + "****";
}
String masked = "*".repeat(digits.length() - 4) + digits.substring(digits.length() - 4);
return (hasPlus ? "+" : "") + masked;
}
try {
UUID.fromString(trimmed);
return "***" + trimmed.substring(trimmed.length() - 6);
} catch (Exception ignored) {
}
int visible = Math.min(4, trimmed.length());
return "***" + trimmed.substring(trimmed.length() - visible);
}

/**
*
* @param notificationDTO
Expand Down Expand Up @@ -734,3 +794,4 @@ public MainResponseDTO<String> getApplicationStatus(String applicationId) {
// }

}

Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.List;
import java.util.Map;

import io.mosip.preregistration.booking.exception.*;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -68,6 +61,9 @@
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.entity.UserDetails;
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;
Expand Down Expand Up @@ -97,6 +93,9 @@ public class BookingServiceUtilTest {
@MockBean
private BookingDAO bookingDAO;

@MockBean
private UserDetailsService userDetailsService;

@Mock
private AuthUserDetails authUserDetails;

Expand Down Expand Up @@ -139,6 +138,10 @@ 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");
UserDetails mappedUser = new UserDetails();
mappedUser.setUserId(java.util.UUID.fromString("00000000-0000-0000-0000-000000000001"));
Mockito.when(userDetailsService.findOrCreateByIdentifier(Mockito.anyString())).thenReturn(mappedUser);
centerDto.setId("10001");
centerDto.setLangCode("eng");
centerDto.setCenterStartTime(startTime);
Expand Down Expand Up @@ -568,6 +571,46 @@ 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 bookingEntitySetterCanonicalFallbackToRawTest() {
ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", true);
Mockito.when(userDetailsService.findOrCreateByIdentifier(Mockito.anyString()))
.thenThrow(new RuntimeException("mapping failed"));
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("test-user", entity.getCrBy());
}

@Test(expected = AppointmentBookingFailedException.class)
public void bookingEntitySetterStrictModeNoRawFallbackTest() {
ReflectionTestUtils.setField(serviceUtil, "piiBackwardCompatibility", false);
Mockito.when(userDetailsService.findOrCreateByIdentifier(Mockito.anyString()))
.thenThrow(new RuntimeException("mapping failed"));
BookingRequestDTO bookingRequestDTO = new BookingRequestDTO();
bookingRequestDTO.setRegistrationCenterId("1");
bookingRequestDTO.setSlotFromTime("09:00");
Expand Down Expand Up @@ -646,3 +689,5 @@ public void timeSpanCheckForRebook1() {
}

}


Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading