diff --git a/pom.xml b/pom.xml index 71666f9..2ed045e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent 3.2.11 - + gov.cms.madie.terminologyservice @@ -14,7 +14,7 @@ Terminology Service Terminology Service for MADiE - 7.4.5 + 7.6.0 16 2.5.0 17 @@ -174,7 +174,7 @@ - + diff --git a/src/main/java/gov/cms/madie/terminology/TerminologyServiceApplication.java b/src/main/java/gov/cms/madie/terminology/TerminologyServiceApplication.java index 0832521..2dfad47 100644 --- a/src/main/java/gov/cms/madie/terminology/TerminologyServiceApplication.java +++ b/src/main/java/gov/cms/madie/terminology/TerminologyServiceApplication.java @@ -25,7 +25,7 @@ public WebMvcConfigurer corsConfigurer() { public void addCorsMappings(CorsRegistry registry) { registry .addMapping("/**") - .allowedMethods("PUT", "POST", "GET") + .allowedMethods("PUT", "POST", "GET", "DELETE") .allowedOrigins( "http://localhost:9000", "https://dev-madie.hcqis.org", diff --git a/src/main/java/gov/cms/madie/terminology/controller/VsacController.java b/src/main/java/gov/cms/madie/terminology/controller/VsacController.java index a73fc16..19b80a8 100644 --- a/src/main/java/gov/cms/madie/terminology/controller/VsacController.java +++ b/src/main/java/gov/cms/madie/terminology/controller/VsacController.java @@ -8,6 +8,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -134,4 +135,12 @@ public ResponseEntity checkUserLogin(Principal principal) { ? ResponseEntity.ok().body(Boolean.TRUE) : new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } + + @DeleteMapping("/umls-credentials") + public ResponseEntity umlsLogout(Principal principal) { + log.info("Entering: umlsLogout(): username = " + principal.getName()); + return vsacService.logoutUMLSUser(principal.getName()) + ? ResponseEntity.ok().body(Boolean.TRUE) + : new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } } diff --git a/src/main/java/gov/cms/madie/terminology/dto/ValueSetsSearchCriteria.java b/src/main/java/gov/cms/madie/terminology/dto/ValueSetsSearchCriteria.java index 2bdc1c3..43e99bc 100644 --- a/src/main/java/gov/cms/madie/terminology/dto/ValueSetsSearchCriteria.java +++ b/src/main/java/gov/cms/madie/terminology/dto/ValueSetsSearchCriteria.java @@ -12,6 +12,7 @@ public class ValueSetsSearchCriteria { private String profile; private String includeDraft; + private String activeOnly; private ManifestExpansion manifestExpansion; private List valueSetParams; diff --git a/src/main/java/gov/cms/madie/terminology/repositories/UmlsUserRepository.java b/src/main/java/gov/cms/madie/terminology/repositories/UmlsUserRepository.java index a13a69f..eb4aaf7 100644 --- a/src/main/java/gov/cms/madie/terminology/repositories/UmlsUserRepository.java +++ b/src/main/java/gov/cms/madie/terminology/repositories/UmlsUserRepository.java @@ -10,4 +10,6 @@ public interface UmlsUserRepository extends MongoRepository { Optional findByHarpId(String harpId); Optional findByHarpIdAndApiKey(String harpId, String apiKey); + + Optional deleteByHarpId(String harpId); } diff --git a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java index 213253d..cc560d7 100644 --- a/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java +++ b/src/main/java/gov/cms/madie/terminology/service/FhirTerminologyService.java @@ -64,6 +64,7 @@ public List recursivelyRequestAllValueSetsExpansionsForQDM( vsParam, valueSetsSearchCriteria.getProfile(), valueSetsSearchCriteria.getIncludeDraft(), + valueSetsSearchCriteria.getActiveOnly(), valueSetsSearchCriteria.getManifestExpansion()); ValueSet valueSetResource = parser.parseResource(ValueSet.class, resource); diff --git a/src/main/java/gov/cms/madie/terminology/service/VsacService.java b/src/main/java/gov/cms/madie/terminology/service/VsacService.java index fa17250..07bab6d 100644 --- a/src/main/java/gov/cms/madie/terminology/service/VsacService.java +++ b/src/main/java/gov/cms/madie/terminology/service/VsacService.java @@ -358,4 +358,15 @@ private List getValueSetConcepts(DescribedValueSet valueSet public Optional findByHarpId(String harpId) { return umlsUserRepository.findByHarpId(harpId); } + + public boolean logoutUMLSUser(String userName) { + Optional deletedUser = umlsUserRepository.deleteByHarpId(userName); + boolean deleted = deletedUser.isPresent(); + if (deleted) { + log.info("Successfully deleted UMLS information for User Name: {}", userName); + } else { + log.error("Error while deleting UMLS information for User Name: {}", userName); + } + return deleted; + } } diff --git a/src/main/java/gov/cms/madie/terminology/util/TerminologyServiceUtil.java b/src/main/java/gov/cms/madie/terminology/util/TerminologyServiceUtil.java index 35f17e2..5ae3bb9 100644 --- a/src/main/java/gov/cms/madie/terminology/util/TerminologyServiceUtil.java +++ b/src/main/java/gov/cms/madie/terminology/util/TerminologyServiceUtil.java @@ -116,6 +116,7 @@ public static URI buildValueSetResourceUri( ValueSetsSearchCriteria.ValueSetParams valueSetParams, String profile, String includeDraft, + String activeOnly, ManifestExpansion manifestExpansion) { MultiValueMap params = new LinkedMultiValueMap<>(); String expandValueSetUri = "/ValueSet/" + valueSetParams.getOid() + "/$expand"; @@ -134,8 +135,12 @@ public static URI buildValueSetResourceUri( } else if (manifestExpansion != null && StringUtils.isNotBlank(manifestExpansion.getFullUrl())) { params.put("manifest", List.of(manifestExpansion.getFullUrl())); - } else if (StringUtils.isNotBlank(includeDraft)) { - params.put("includeDraft", List.of("true")); + } else { + if (StringUtils.isNotBlank(includeDraft)) { + params.put("includeDraft", List.of("true")); + } + + params.put("activeOnly", List.of(activeOnly)); } return UriComponentsBuilder.fromPath(expandValueSetUri).queryParams(params).build().toUri(); diff --git a/src/main/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClient.java b/src/main/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClient.java index 395054c..8ac2131 100644 --- a/src/main/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClient.java +++ b/src/main/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClient.java @@ -108,11 +108,12 @@ public String getValueSetResource( ValueSetsSearchCriteria.ValueSetParams valueSetParams, String profile, String includeDraft, + String activeOnly, ManifestExpansion manifestExpansion) { profile = StringUtils.isNotBlank(profile) ? defaultProfile : profile; URI uri = TerminologyServiceUtil.buildValueSetResourceUri( - valueSetParams, profile, includeDraft, manifestExpansion); + valueSetParams, profile, includeDraft, activeOnly, manifestExpansion); return fetchResourceFromVsac(uri.toString(), apiKey, "ValueSet"); } diff --git a/src/test/java/gov/cms/madie/terminology/controller/VsacControllerTest.java b/src/test/java/gov/cms/madie/terminology/controller/VsacControllerTest.java index a155cd1..f2d9c50 100644 --- a/src/test/java/gov/cms/madie/terminology/controller/VsacControllerTest.java +++ b/src/test/java/gov/cms/madie/terminology/controller/VsacControllerTest.java @@ -133,4 +133,26 @@ void testInvalidUserUmlsLogin() { assertEquals(response.getStatusCode(), HttpStatus.UNAUTHORIZED); } + + @Test + void testUserUmlsLogout() { + Principal principal = mock(Principal.class); + when(principal.getName()).thenReturn(TEST_USER); + + when(vsacService.logoutUMLSUser(anyString())).thenReturn(true); + ResponseEntity response = vsacController.umlsLogout(principal); + + assertEquals(response.getBody(), Boolean.TRUE); + } + + @Test + void testUserUmlsLogoutFailed() { + Principal principal = mock(Principal.class); + when(principal.getName()).thenReturn(TEST_USER); + + when(vsacService.logoutUMLSUser(anyString())).thenReturn(false); + ResponseEntity response = vsacController.umlsLogout(principal); + + assertEquals(response.getStatusCode(), HttpStatus.UNAUTHORIZED); + } } diff --git a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java index 78a012d..1fd0f67 100644 --- a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java @@ -173,6 +173,7 @@ void getValueSetsExpansionsForQdm_When_ManifestExpansionIsProvided() { .build())) .profile("test-profile") .includeDraft("false") + .activeOnly("true") .manifestExpansion( ManifestExpansion.builder() .fullUrl("https://cts.nlm.nih.gov/fhir/Library/ecqm-update-2022-05-05") @@ -180,7 +181,7 @@ void getValueSetsExpansionsForQdm_When_ManifestExpansionIsProvided() { .build()) .build(); when(fhirTerminologyServiceWebClient.getValueSetResource( - anyString(), any(), anyString(), anyString(), any())) + anyString(), any(), anyString(), anyString(), anyString(), any())) .thenReturn(mockValueSetResourceWithCodes); when(fhirContext.newJsonParser()).thenReturn(FhirContext.forR4().newJsonParser()); when(mappingService.getCodeSystemEntries()).thenReturn(codeSystemEntries); @@ -209,6 +210,7 @@ void getsValueSetsExpansionsForQdm_withNoCodes_When_ManifestExpansionIsProvided( .build())) .profile("test-profile") .includeDraft("false") + .activeOnly("false") .manifestExpansion( ManifestExpansion.builder() .fullUrl("https://cts.nlm.nih.gov/fhir/Library/ecqm-update-2022-05-05") @@ -221,6 +223,7 @@ void getsValueSetsExpansionsForQdm_withNoCodes_When_ManifestExpansionIsProvided( any(ValueSetsSearchCriteria.ValueSetParams.class), anyString(), anyString(), + anyString(), any(ManifestExpansion.class))) .thenReturn(mockValueSetResourceWithNoCodes); when(mappingService.getCodeSystemEntries()).thenReturn(codeSystemEntries); diff --git a/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java b/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java index b0148d9..45bc796 100644 --- a/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java +++ b/src/test/java/gov/cms/madie/terminology/service/VsacServiceTest.java @@ -592,4 +592,18 @@ void testGetCodeStatusIfCodeNotFoundInSvs() { CodeStatus status = vsacService.getCodeStatus(code, TEST_API_KEY); assertThat(status, is(equalTo(CodeStatus.NA))); } + + @Test + void testUserUmlsLogout() { + when(umlsUserRepository.deleteByHarpId(anyString())).thenReturn(Optional.of(umlsUser)); + boolean loggedOut = vsacService.logoutUMLSUser(umlsUser.getHarpId()); + assertTrue(loggedOut); + } + + @Test + void testUserUmlsLogoutFailed() { + when(umlsUserRepository.deleteByHarpId(anyString())).thenReturn(Optional.empty()); + boolean loggedOut = vsacService.logoutUMLSUser(umlsUser.getHarpId()); + assertFalse(loggedOut); + } } diff --git a/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java b/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java index 10c84f2..06cc5c2 100644 --- a/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java +++ b/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java @@ -91,11 +91,11 @@ void getLatestValueSetResourceSuccessfully_when_noCustomSearchCriteriaIsProvided .addHeader("Content-Type", "application/fhir+json")); String actualResponse = fhirTerminologyServiceWebClient.getValueSetResource( - MOCK_API_KEY, testValueSetParams, null, null, new ManifestExpansion()); + MOCK_API_KEY, testValueSetParams, null, null, "false", new ManifestExpansion()); assertNotNull(actualResponse); assertEquals(MOCK_RESPONSE_STRING, actualResponse); RecordedRequest recordedRequest = mockBackEnd.takeRequest(); - assertEquals("/ValueSet/test-vs-id/$expand", recordedRequest.getPath()); + assertEquals("/ValueSet/test-vs-id/$expand?activeOnly=false", recordedRequest.getPath()); } @Test @@ -108,11 +108,13 @@ void getDraftValueSetResourceSuccessfully_when_noCustomSearchCriteriaIsProvided( .addHeader("Content-Type", "application/fhir+json")); String actualResponse = fhirTerminologyServiceWebClient.getValueSetResource( - MOCK_API_KEY, testValueSetParams, null, "yes", new ManifestExpansion()); + MOCK_API_KEY, testValueSetParams, null, "yes", "false", new ManifestExpansion()); assertNotNull(actualResponse); assertEquals(MOCK_RESPONSE_STRING, actualResponse); RecordedRequest recordedRequest = mockBackEnd.takeRequest(); - assertEquals("/ValueSet/test-vs-id/$expand?includeDraft=true", recordedRequest.getPath()); + assertEquals( + "/ValueSet/test-vs-id/$expand?includeDraft=true&activeOnly=false", + recordedRequest.getPath()); } @Test @@ -129,6 +131,7 @@ void getValueSetResourceSuccessfully_when_manifestExpansionIsProvided() testValueSetParams, null, null, + "true", ManifestExpansion.builder() .id("test-manifest-456") .fullUrl("https://cts.nlm.nih.gov/fhir/Library/test-manifest-456") @@ -152,7 +155,7 @@ void getValueSetResourceSuccessfully_when_ValueSetVersionIsProvided() testValueSetParams.setVersion("test-value-set-version-2024"); String actualResponse = fhirTerminologyServiceWebClient.getValueSetResource( - MOCK_API_KEY, testValueSetParams, null, null, new ManifestExpansion()); + MOCK_API_KEY, testValueSetParams, null, null, "false", new ManifestExpansion()); assertNotNull(actualResponse); assertEquals(MOCK_RESPONSE_STRING, actualResponse); RecordedRequest recordedRequest = mockBackEnd.takeRequest(); @@ -169,9 +172,9 @@ void getValueSetResource_ReturnsException() throws InterruptedException { WebClientResponseException.class, () -> fhirTerminologyServiceWebClient.getValueSetResource( - MOCK_API_KEY, testValueSetParams, null, null, new ManifestExpansion())); + MOCK_API_KEY, testValueSetParams, null, null, "false", new ManifestExpansion())); RecordedRequest recordedRequest = mockBackEnd.takeRequest(); - assertEquals("/ValueSet/test-vs-id/$expand", recordedRequest.getPath()); + assertEquals("/ValueSet/test-vs-id/$expand?activeOnly=false", recordedRequest.getPath()); } @Test