diff --git a/Dockerfile b/Dockerfile index 6a02f4b..b38cea0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,4 +2,4 @@ FROM adoptopenjdk/openjdk11:jre-11.0.8_10-alpine VOLUME /tmp COPY build/libs/* app.jar EXPOSE 8000 -ENTRYPOINT ["java", "-jar", "/app.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"] \ No newline at end of file diff --git a/pipelines/Jenkinsfile b/pipelines/Jenkinsfile new file mode 100644 index 0000000..f50dc10 --- /dev/null +++ b/pipelines/Jenkinsfile @@ -0,0 +1,103 @@ +pipeline { + agent { + kubernetes { + yaml """ + apiVersion: v1 + kind: Pod + spec: + containers: + - name: docker + image: registry.nhadclmgm.tcl.com:5000/docker:dind + securityContext: + privileged: true + resources: + limits: + cpu: '300m' + memory: '500Mi' + requests: + cpu: '100m' + memory: '300Mi' + - name: java11 + image: adoptopenjdk/maven-openjdk11 + command: + - sleep + args: + - infinity + resources: + limits: + cpu: '1000m' + memory: '2000Mi' + requests: + cpu: '400m' + memory: '1200Mi' + """ + defaultContainer 'java11' + } + } + + options { + skipDefaultCheckout() + } + + environment { + def IMAGE_NAME= 'gateway' + def DOCKER_FILE_DIRECTORY = "Dockerfile" + def DOCKER_HARBOR_URL = "harbor.nhadclmgm.tatacommunications.com" + def HARBOR_REPO = "gateway" + def IMAGE_TAG = "latest" + def IMAGE_REPO = "${DOCKER_HARBOR_URL + '/' + HARBOR_REPO + '/'+ IMAGE_NAME}" + def IMAGE = "${IMAGE_REPO + ':' + IMAGE_TAG}" + } + + stages { + stage('Get latest version of code') { + steps { + script{ + def scmVar = checkout([ + $class: 'GitSCM', branches: scm.branches, + extensions: scm.extensions + [[$class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true]], + userRemoteConfigs: scm.userRemoteConfigs]) + sh "echo ${scmVar.GIT_COMMIT} | head -c7 >> commit_sha.txt" + if(env.TAG_NAME){ + sh "echo $TAG_NAME > commit_sha.txt" + sh "cat commit_sha.txt" + } + } + } + } + + stage("Run tests and Build"){ + steps{ + container('java11'){ + sh "./gradlew clean test" + sh "./gradlew clean bootJar" + } + } + } + + stage ('Build Docker Image and Push to NHA Harbor') { + when { + anyOf{ + branch 'master' + buildingTag() + } + } + steps { + withCredentials([ + usernamePassword(credentialsId: 'NDHM_HARBOR_HUB_PASSWORD_GATEWAY', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')] + ){ + container('docker'){ + script{ + def COMMIT_SHA=readFile(file: 'commit_sha.txt') + dockerImage = docker.build IMAGE + sh "docker login ${DOCKER_HARBOR_URL} -u ${USERNAME} -p ${PASSWORD}" + sh "docker push ${IMAGE}" + sh "docker tag ${IMAGE_REPO} ${IMAGE_REPO}:${COMMIT_SHA}" + sh "docker push ${IMAGE_REPO}:${COMMIT_SHA}" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/in/projecteka/gateway/GatewayConfiguration.java b/src/main/java/in/projecteka/gateway/GatewayConfiguration.java index e7d9743..7557506 100644 --- a/src/main/java/in/projecteka/gateway/GatewayConfiguration.java +++ b/src/main/java/in/projecteka/gateway/GatewayConfiguration.java @@ -22,6 +22,7 @@ import in.projecteka.gateway.clients.HealthInfoNotificationServiceClient; import in.projecteka.gateway.clients.HipConsentNotifyServiceClient; import in.projecteka.gateway.clients.HipDataFlowServiceClient; +import in.projecteka.gateway.clients.HipDataNotificationServiceClient; import in.projecteka.gateway.clients.HipInitLinkServiceClient; import in.projecteka.gateway.clients.HiuConsentNotifyServiceClient; import in.projecteka.gateway.clients.HiuSubscriptionNotifyServiceClient; @@ -98,6 +99,8 @@ import reactor.rabbitmq.ReceiverOptions; import reactor.rabbitmq.SenderOptions; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.time.Duration; import java.util.concurrent.TimeUnit; @@ -907,12 +910,15 @@ public ResponseOrchestrator authConfirmResponseOrchestrator( } @Bean - public ConnectionFactory connectionFactory(RabbitmqOptions rabbitmqOptions) { + public ConnectionFactory connectionFactory(RabbitmqOptions rabbitmqOptions) throws KeyManagementException, NoSuchAlgorithmException { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost(rabbitmqOptions.getHost()); connectionFactory.setPort(rabbitmqOptions.getPort()); connectionFactory.setUsername(rabbitmqOptions.getUsername()); connectionFactory.setPassword(rabbitmqOptions.getPassword()); + if(rabbitmqOptions.isUseSSL()){ + connectionFactory.useSslProtocol(); + } connectionFactory.useNio(); return connectionFactory; } @@ -1421,4 +1427,46 @@ public ResponseOrchestrator patientSMSNotifyResponseOrchestrator( DefaultValidatedResponseAction patientSMSNotificationResponseAction) { return new ResponseOrchestrator(validator, patientSMSNotificationResponseAction); } + + @Bean("hipDataNotificationServiceClient") + public HipDataNotificationServiceClient hipDataNotificationServiceClient(ServiceOptions serviceOptions, + @Qualifier("customBuilder") WebClient.Builder builder, + CMRegistry cmRegistry, + IdentityService identityService, + BridgeRegistry bridgeRegistry) { + return new HipDataNotificationServiceClient(serviceOptions, builder, identityService, cmRegistry, bridgeRegistry); + } + + @Bean("hipDataNotificationRequestAction") + public DefaultValidatedRequestAction hipDataNotificationRequestAction( + HipDataNotificationServiceClient hipDataNotificationServiceClient) { + return new DefaultValidatedRequestAction<>(hipDataNotificationServiceClient); + } + + @Bean("hipDataNotificationRequestOrchestrator") + public RequestOrchestrator hipDataNotificationRequestOrchestrator( + @Qualifier("requestIdMappings") CacheAdapter requestIdMappings, + RedundantRequestValidator redundantRequestValidator, + Validator validator, + HipDataNotificationServiceClient hipDataNotificationServiceClient, + DefaultValidatedRequestAction hipDataNotificationRequestAction) { + return new RequestOrchestrator<>(requestIdMappings, + redundantRequestValidator, + validator, + hipDataNotificationServiceClient, + hipDataNotificationRequestAction); + } + + @Bean("hipDataNotificationResponseAction") + public DefaultValidatedResponseAction hipDataNotificationResponseAction( + HipDataNotificationServiceClient hipDataNotificationServiceClient) { + return new DefaultValidatedResponseAction<>(hipDataNotificationServiceClient); + } + + @Bean("hipDataNotificationResponseOrchestrator") + public ResponseOrchestrator hipDataNotificationResponseOrchestrator( + Validator validator, + DefaultValidatedResponseAction hipDataNotificationResponseAction) { + return new ResponseOrchestrator(validator, hipDataNotificationResponseAction); + } } diff --git a/src/main/java/in/projecteka/gateway/MdcContextLifterConfiguration.java b/src/main/java/in/projecteka/gateway/MdcContextLifterConfiguration.java index 59d0896..ea6793a 100644 --- a/src/main/java/in/projecteka/gateway/MdcContextLifterConfiguration.java +++ b/src/main/java/in/projecteka/gateway/MdcContextLifterConfiguration.java @@ -1,5 +1,6 @@ package in.projecteka.gateway; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; import reactor.core.publisher.Hooks; import reactor.core.publisher.Operators; @@ -8,6 +9,7 @@ import javax.annotation.PreDestroy; @Configuration +@ConditionalOnProperty(value = "logging.correlation-enabled", havingValue = "true") public class MdcContextLifterConfiguration { private String MDC_CONTEXT_REACTOR_KEY = in.projecteka.gateway.MdcContextLifterConfiguration.class.getName(); diff --git a/src/main/java/in/projecteka/gateway/SecurityConfiguration.java b/src/main/java/in/projecteka/gateway/SecurityConfiguration.java index c5fa092..99ab626 100644 --- a/src/main/java/in/projecteka/gateway/SecurityConfiguration.java +++ b/src/main/java/in/projecteka/gateway/SecurityConfiguration.java @@ -33,6 +33,7 @@ import static in.projecteka.gateway.common.Constants.HFR_BRIDGES_BRIDGE_ID_SERVICES; import static in.projecteka.gateway.common.Constants.INTERNAL_BRIDGES; import static in.projecteka.gateway.common.Constants.INTERNAL_BRIDGES_BRIDGE_ID_SERVICES; +import static in.projecteka.gateway.common.Constants.INTERNAL_PATH_GET_GOVT_PROGRAMS_LIST; import static in.projecteka.gateway.common.Constants.INTERNAL_CM; import static in.projecteka.gateway.common.Constants.INTERNAL_GET_FACILITY_BY_ID; import static in.projecteka.gateway.common.Constants.INTERNAL_SEARCH_FACILITY_BY_NAME; @@ -57,6 +58,8 @@ import static in.projecteka.gateway.common.Constants.PATH_HEALTH_INFORMATION_HIP_REQUEST; import static in.projecteka.gateway.common.Constants.PATH_HEALTH_INFORMATION_NOTIFY; import static in.projecteka.gateway.common.Constants.PATH_HEARTBEAT; +import static in.projecteka.gateway.common.Constants.PATH_HIP_DATA_NOTIFICATION; +import static in.projecteka.gateway.common.Constants.PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT; import static in.projecteka.gateway.common.Constants.PATH_HIU_SUBSCRIPTION_NOTIFY; import static in.projecteka.gateway.common.Constants.PATH_HIU_SUBSCRIPTION_ON_NOTIFY; import static in.projecteka.gateway.common.Constants.PATH_LINK_CONFIRM; @@ -117,7 +120,8 @@ public class SecurityConfiguration { PATH_HEALTH_INFORMATION_HIP_ON_REQUEST, PATH_ADD_CARE_CONTEXTS, PATH_PATIENT_ON_SHARE, - PATH_PATIENTS_SMS_NOTIFY + PATH_PATIENTS_SMS_NOTIFY, + PATH_HIP_DATA_NOTIFICATION }; protected static final String[] HIU_HIP_APIS = new String[]{ @@ -147,11 +151,13 @@ public class SecurityConfiguration { PATH_CONSENT_REQUEST_ON_STATUS, PATH_PATIENT_SHARE, PATH_ON_FETCH_AUTH_MODES, + PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT, PATH_HIU_SUBSCRIPTION_NOTIFY, PATH_SUBSCRIPTION_REQUESTS_NOTIFY, INTERNAL_SEARCH_FACILITY_BY_NAME, INTERNAL_GET_FACILITY_BY_ID, - PATH_PATIENTS_SMS_ON_NOTIFY + PATH_PATIENTS_SMS_ON_NOTIFY, + INTERNAL_PATH_GET_GOVT_PROGRAMS_LIST }; protected static final String[] ALLOW_LIST_APIS = { diff --git a/src/main/java/in/projecteka/gateway/clients/HipDataNotificationServiceClient.java b/src/main/java/in/projecteka/gateway/clients/HipDataNotificationServiceClient.java new file mode 100644 index 0000000..541238a --- /dev/null +++ b/src/main/java/in/projecteka/gateway/clients/HipDataNotificationServiceClient.java @@ -0,0 +1,35 @@ +package in.projecteka.gateway.clients; + +import in.projecteka.gateway.common.Constants; +import in.projecteka.gateway.common.IdentityService; +import in.projecteka.gateway.common.cache.ServiceOptions; +import in.projecteka.gateway.registry.BridgeRegistry; +import in.projecteka.gateway.registry.CMRegistry; +import in.projecteka.gateway.registry.ServiceType; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +public class HipDataNotificationServiceClient extends ServiceClient { + private final CMRegistry cmRegistry; + private final BridgeRegistry bridgeRegistry; + + public HipDataNotificationServiceClient(ServiceOptions serviceOptions, + WebClient.Builder webClientBuilder, + IdentityService identityService, + CMRegistry cmRegistry, + BridgeRegistry bridgeRegistry) { + super(serviceOptions, webClientBuilder, identityService); + this.cmRegistry = cmRegistry; + this.bridgeRegistry = bridgeRegistry; + } + + @Override + protected Mono getResponseUrl(String clientId, ServiceType serviceType) { + return bridgeRegistry.getHostFor(clientId, serviceType).map(host -> host + Constants.PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT); + } + + @Override + protected Mono getRequestUrl(String clientId, ServiceType serviceType) { + return cmRegistry.getHostFor(clientId).map(host -> host + Constants.PATH_HIP_DATA_NOTIFICATION); + } +} diff --git a/src/main/java/in/projecteka/gateway/common/Constants.java b/src/main/java/in/projecteka/gateway/common/Constants.java index 6328693..2e0c804 100644 --- a/src/main/java/in/projecteka/gateway/common/Constants.java +++ b/src/main/java/in/projecteka/gateway/common/Constants.java @@ -86,6 +86,8 @@ public class Constants { public static final String PATH_HIU_SUBSCRIPTION_ON_NOTIFY = CURRENT_VERSION + "/subscriptions/hiu/on-notify"; public static final String PATH_PATIENTS_SMS_NOTIFY = CURRENT_VERSION + "/patients/sms/notify"; public static final String PATH_PATIENTS_SMS_ON_NOTIFY = CURRENT_VERSION + "/patients/sms/on-notify"; + public static final String PATH_HIP_DATA_NOTIFICATION = CURRENT_VERSION + "/links/context/notify"; + public static final String PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT = CURRENT_VERSION + "/links/context/on-notify"; public static final String ROUTE_PATH_CM_HIU_SUBSCRIPTION_ON_NOTIFY = CURRENT_VERSION + "/subscriptions/on-notify"; public static final String GW_PATH_HI_SERVICE_BY_ID = CURRENT_VERSION + "/hi-services/{service-id}"; public static final String GW_PATH_HI_SERVICES = CURRENT_VERSION + "/hi-services"; @@ -93,6 +95,7 @@ public class Constants { public static final String HFR_BRIDGES_BRIDGE_ID_SERVICES = "/bridges/{bridgeId}/services"; public static final String INTERNAL_SEARCH_FACILITY_BY_NAME = CURRENT_VERSION + "/internal/facilities"; public static final String INTERNAL_GET_FACILITY_BY_ID = CURRENT_VERSION + "/internal/facilities/{serviceId}"; + public static final String INTERNAL_PATH_GET_GOVT_PROGRAMS_LIST = CURRENT_VERSION + "/internal/govt-programs"; //API to be called on HIP/HIU bridge public static final String PATH_BRIDGE_ON_FETCH_AUTH_MODES = CURRENT_VERSION + "/users/auth/on-fetch-modes"; diff --git a/src/main/java/in/projecteka/gateway/common/heartbeat/Heartbeat.java b/src/main/java/in/projecteka/gateway/common/heartbeat/Heartbeat.java index 509b722..8496549 100644 --- a/src/main/java/in/projecteka/gateway/common/heartbeat/Heartbeat.java +++ b/src/main/java/in/projecteka/gateway/common/heartbeat/Heartbeat.java @@ -10,6 +10,8 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeoutException; import static in.projecteka.gateway.clients.model.Error.of; @@ -34,17 +36,20 @@ public Mono getStatus() { return (cacheHealth.isUp() && isRabbitMQUp() && isKeycloakUp()) ? just(HeartbeatResponse.builder().timeStamp(now(UTC)).status(UP).build()) : just(HeartbeatResponse.builder().timeStamp(now(UTC)).status(DOWN).error(of(SERVICE_DOWN)).build()); - } catch (IOException | TimeoutException e) { + } catch (IOException | TimeoutException | KeyManagementException | NoSuchAlgorithmException e) { return just(HeartbeatResponse.builder().timeStamp(now(UTC)).status(DOWN).error(of(SERVICE_DOWN)).build()); } } - private boolean isRabbitMQUp() throws IOException, TimeoutException { + private boolean isRabbitMQUp() throws IOException, TimeoutException, KeyManagementException, NoSuchAlgorithmException { var factory = new ConnectionFactory(); factory.setHost(rabbitmqOptions.getHost()); factory.setPort(rabbitmqOptions.getPort()); factory.setUsername(rabbitmqOptions.getUsername()); factory.setPassword(rabbitmqOptions.getPassword()); + if(rabbitmqOptions.isUseSSL()){ + factory.useSslProtocol(); + } try (Connection connection = factory.newConnection()) { return connection.isOpen(); } diff --git a/src/main/java/in/projecteka/gateway/common/heartbeat/RabbitmqOptions.java b/src/main/java/in/projecteka/gateway/common/heartbeat/RabbitmqOptions.java index 8fe22af..fb9a36f 100644 --- a/src/main/java/in/projecteka/gateway/common/heartbeat/RabbitmqOptions.java +++ b/src/main/java/in/projecteka/gateway/common/heartbeat/RabbitmqOptions.java @@ -15,4 +15,5 @@ public class RabbitmqOptions { private final int channelPoolMaxCacheSize; private final String username; private final String password; + private final boolean useSSL; } diff --git a/src/main/java/in/projecteka/gateway/data_notification/DataNotificationController.java b/src/main/java/in/projecteka/gateway/data_notification/DataNotificationController.java new file mode 100644 index 0000000..313be46 --- /dev/null +++ b/src/main/java/in/projecteka/gateway/data_notification/DataNotificationController.java @@ -0,0 +1,47 @@ +package in.projecteka.gateway.data_notification; + +import in.projecteka.gateway.clients.HipDataNotificationServiceClient; +import in.projecteka.gateway.common.Caller; +import in.projecteka.gateway.common.RequestOrchestrator; +import in.projecteka.gateway.common.ResponseOrchestrator; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.context.ReactiveSecurityContextHolder; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import static in.projecteka.gateway.common.Constants.API_CALLED; +import static in.projecteka.gateway.common.Constants.PATH_HIP_DATA_NOTIFICATION; +import static in.projecteka.gateway.common.Constants.PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT; +import static in.projecteka.gateway.common.Constants.X_CM_ID; +import static in.projecteka.gateway.common.Constants.X_HIP_ID; +import static in.projecteka.gateway.common.Constants.bridgeId; + + +@RestController +@AllArgsConstructor +public class DataNotificationController { + RequestOrchestrator hipDataNotificationRequestOrchestrator; + ResponseOrchestrator hipDataNotificationResponseOrchestrator; + + @ResponseStatus(HttpStatus.ACCEPTED) + @PostMapping(PATH_HIP_DATA_NOTIFICATION) + public Mono hipDataNotification(HttpEntity requestEntity) { + return ReactiveSecurityContextHolder.getContext() + .map(securityContext -> (Caller) securityContext.getAuthentication().getPrincipal()) + .map(Caller::getClientId) + .flatMap(clientId -> hipDataNotificationRequestOrchestrator + .handleThis(requestEntity, X_CM_ID, X_HIP_ID, bridgeId(clientId)) + .subscriberContext(context -> context.put(API_CALLED, PATH_HIP_DATA_NOTIFICATION))); + } + + @ResponseStatus(HttpStatus.ACCEPTED) + @PostMapping(PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT) + public Mono hipDataNotificationAcknowledgement(HttpEntity requestEntity) { + return hipDataNotificationResponseOrchestrator.processResponse(requestEntity, X_HIP_ID) + .subscriberContext(context -> context.put(API_CALLED, PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT)); + } +} diff --git a/src/main/java/in/projecteka/gateway/registry/RegistryController.java b/src/main/java/in/projecteka/gateway/registry/RegistryController.java index b40011e..3fa69ba 100644 --- a/src/main/java/in/projecteka/gateway/registry/RegistryController.java +++ b/src/main/java/in/projecteka/gateway/registry/RegistryController.java @@ -28,6 +28,7 @@ import static in.projecteka.gateway.common.Constants.INTERNAL_BRIDGES_BRIDGE_ID_SERVICES; import static in.projecteka.gateway.common.Constants.INTERNAL_CM; import static in.projecteka.gateway.common.Constants.INTERNAL_GET_FACILITY_BY_ID; +import static in.projecteka.gateway.common.Constants.INTERNAL_PATH_GET_GOVT_PROGRAMS_LIST; import static in.projecteka.gateway.common.Constants.INTERNAL_SEARCH_FACILITY_BY_NAME; import static in.projecteka.gateway.common.Constants.UNSPECIFIED_SERVICE_TYPE; @@ -79,4 +80,9 @@ public Mono> searchFacilityByName(@RequestParam Str public Mono searchFacilityByName(@PathVariable String serviceId) { return registryService.getFacilityById(serviceId); } + + @GetMapping(INTERNAL_PATH_GET_GOVT_PROGRAMS_LIST) + public Mono> fetchGovtPrograms() { + return registryService.fetchGovtPrograms(); + } } diff --git a/src/main/java/in/projecteka/gateway/registry/RegistryRepository.java b/src/main/java/in/projecteka/gateway/registry/RegistryRepository.java index 6062968..ae57911 100644 --- a/src/main/java/in/projecteka/gateway/registry/RegistryRepository.java +++ b/src/main/java/in/projecteka/gateway/registry/RegistryRepository.java @@ -1,6 +1,5 @@ package in.projecteka.gateway.registry; -import in.projecteka.gateway.clients.ClientError; import in.projecteka.gateway.common.DbOperationError; import in.projecteka.gateway.registry.model.Bridge; import in.projecteka.gateway.registry.model.BridgeRegistryRequest; @@ -29,7 +28,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import static in.projecteka.gateway.common.Serializer.from; import static in.projecteka.gateway.common.Serializer.to; @@ -72,6 +70,9 @@ public class RegistryRepository { private static final String SELECT_FACILITIES_BY_NAME = "SELECT service_id, name, is_hip, is_hiu, is_health_locker " + "FROM bridge_service WHERE UPPER(name) LIKE $1 AND is_hip = true"; + private static final String SELECT_GOVT_PROGRAMS = "SELECT service_id, gp.name as name, is_hip, is_hiu, is_health_locker " + + " FROM bridge_service INNER JOIN govt_programs AS gp ON gp.hip_id = service_id" + + " WHERE active = true AND is_hip = true"; private final PgPool readWriteClient; private final PgPool readOnlyClient; @@ -496,4 +497,21 @@ private FacilityRepresentation toFacilityRepresentation(Row row) { .facilityType(serviceTypes) .build(); } + + public Flux fetchGovtPrograms() { + return Flux.create(fluxSink -> this.readOnlyClient.preparedQuery(SELECT_GOVT_PROGRAMS) + .execute(handler -> { + if (handler.failed()) { + logger.error(handler.cause().getMessage(), handler.cause()); + fluxSink.error(new DbOperationError("Failed to fetch govt programs")); + return; + } + RowSet rowSet = handler.result(); + for (var row: rowSet) { + fluxSink.next(toFacilityRepresentation(row)); + } + + fluxSink.complete(); + })); + } } diff --git a/src/main/java/in/projecteka/gateway/registry/RegistryService.java b/src/main/java/in/projecteka/gateway/registry/RegistryService.java index 837e5e7..7807af3 100644 --- a/src/main/java/in/projecteka/gateway/registry/RegistryService.java +++ b/src/main/java/in/projecteka/gateway/registry/RegistryService.java @@ -374,5 +374,9 @@ public Mono getFacilityById(String serviceId) { .build(); }); } + + public Mono> fetchGovtPrograms(){ + return registryRepository.fetchGovtPrograms().collectList(); + } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index f5f55b8..e816b90 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -6,6 +6,7 @@ spring: port: 5672 username: guest password: guest + useSSL: false identity: clientId: gateway clientSecret: ${CLIENT_SECRET} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index ea70a68..ea99a4e 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -42,6 +42,7 @@ spring: username: ${RABBITMQ_USERNAME:guest} password: ${RABBITMQ_PASSWORD:guest} channelPoolMaxCacheSize: ${RABBITMQ_CHANNEL_POOL_SIZE:10} + useSSL: ${RABBITMQ_USE_SSL:true} identity: clientId: ${GATEWAY_CLIENT_ID} clientSecret: ${GATEWAY_CLIENT_SECRET} @@ -67,3 +68,4 @@ webclient: logging: level: ROOT: ${LOG_LEVEL:INFO} + correlation-enabled: ${LOG_CORRELATION_ID:true} diff --git a/src/test/java/in/projecteka/gateway/data_notification/DataNotificationControllerTest.java b/src/test/java/in/projecteka/gateway/data_notification/DataNotificationControllerTest.java new file mode 100644 index 0000000..31e233b --- /dev/null +++ b/src/test/java/in/projecteka/gateway/data_notification/DataNotificationControllerTest.java @@ -0,0 +1,96 @@ +package in.projecteka.gateway.data_notification; + +import com.nimbusds.jose.jwk.JWKSet; +import in.projecteka.gateway.clients.HipDataNotificationServiceClient; +import in.projecteka.gateway.common.Authenticator; +import in.projecteka.gateway.common.Constants; +import in.projecteka.gateway.common.RequestOrchestrator; +import in.projecteka.gateway.common.ResponseOrchestrator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Mono; + +import java.util.List; + +import static in.projecteka.gateway.common.Constants.BRIDGE_ID_PREFIX; +import static in.projecteka.gateway.common.Constants.X_CM_ID; +import static in.projecteka.gateway.common.Constants.X_HIP_ID; +import static in.projecteka.gateway.common.Role.CM; +import static in.projecteka.gateway.common.Role.HIP; +import static in.projecteka.gateway.testcommon.TestBuilders.caller; +import static in.projecteka.gateway.testcommon.TestBuilders.string; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpHeaders.AUTHORIZATION; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static reactor.core.publisher.Mono.empty; +import static reactor.core.publisher.Mono.just; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureWebTestClient +class DataNotificationControllerTest { + @MockBean + @Qualifier("hipDataNotificationRequestOrchestrator") + RequestOrchestrator hipDataNotificationRequestOrchestrator; + + @Autowired + WebTestClient webTestClient; + + @MockBean(name = "centralRegistryJWKSet") + JWKSet centralRegistryJWKSet; + + @MockBean + Authenticator authenticator; + + @Qualifier("hipDataNotificationResponseOrchestrator") + @MockBean + ResponseOrchestrator hipDataNotificationResponseOrchestrator; + + @Test + void shouldFireAndForgetForHipDataNotification() { + var token = string(); + var clientId = string(); + when(hipDataNotificationRequestOrchestrator + .handleThis(any(), eq(X_CM_ID), eq(X_HIP_ID), eq(BRIDGE_ID_PREFIX + clientId))) + .thenReturn(empty()); + when(authenticator.verify(token)) + .thenReturn(just(caller().clientId(clientId).roles(List.of(HIP)).build())); + + webTestClient + .post() + .uri(Constants.PATH_HIP_DATA_NOTIFICATION) + .header(AUTHORIZATION, token) + .contentType(APPLICATION_JSON) + .bodyValue("{}") + .exchange() + .expectStatus() + .isAccepted(); + } + + @Test + void shouldFireAndForgetForHipDataNotificationAcknowledgment() { + var token = string(); + when(authenticator.verify(token)).thenReturn(just(caller().roles(List.of(CM)).build())); + when(hipDataNotificationResponseOrchestrator.processResponse(any(), eq(X_HIP_ID))) + .thenReturn(Mono.empty()); + + webTestClient + .post() + .uri(Constants.PATH_HIP_DATA_NOTIFICATION_ACKNOWLEDGEMENT) + .contentType(APPLICATION_JSON) + .header(AUTHORIZATION, token) + .bodyValue("{}") + .exchange() + .expectStatus() + .isAccepted(); + } +}