diff --git a/pom.xml b/pom.xml
index 87938d1..a776509 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
@@ -167,7 +167,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/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/VsacService.java b/src/main/java/gov/cms/madie/terminology/service/VsacService.java
index fa17250..084cc52 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,13 @@ private List getValueSetConcepts(DescribedValueSet valueSet
public Optional findByHarpId(String harpId) {
return umlsUserRepository.findByHarpId(harpId);
}
+
+ public boolean logoutUMLSUser(String userName) {
+ UmlsUser user = verifyUmlsAccess(userName);
+ boolean deleted = false;
+ Optional deletedUser = umlsUserRepository.deleteByHarpId(userName);
+ deleted = deletedUser.isPresent();
+ log.info("Log out UMLS User:{} : {}.", user.getHarpId(), deleted);
+ return deleted;
+ }
}
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 f3b6ca1..1fd0f67 100644
--- a/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java
+++ b/src/test/java/gov/cms/madie/terminology/service/FhirTerminologyServiceTest.java
@@ -219,12 +219,12 @@ void getsValueSetsExpansionsForQdm_withNoCodes_When_ManifestExpansionIsProvided(
.build();
when(fhirContext.newJsonParser()).thenReturn(FhirContext.forR4().newJsonParser());
when(fhirTerminologyServiceWebClient.getValueSetResource(
- anyString(),
- any(ValueSetsSearchCriteria.ValueSetParams.class),
- anyString(),
- anyString(),
- anyString(),
- any(ManifestExpansion.class)))
+ anyString(),
+ any(ValueSetsSearchCriteria.ValueSetParams.class),
+ anyString(),
+ anyString(),
+ anyString(),
+ any(ManifestExpansion.class)))
.thenReturn(mockValueSetResourceWithNoCodes);
when(mappingService.getCodeSystemEntries()).thenReturn(codeSystemEntries);
List result =
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..e9f515c 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,34 @@ void testGetCodeStatusIfCodeNotFoundInSvs() {
CodeStatus status = vsacService.getCodeStatus(code, TEST_API_KEY);
assertThat(status, is(equalTo(CodeStatus.NA)));
}
+
+ @Test
+ void testUserUmlsLogout() {
+ when(umlsUserRepository.findByHarpId(anyString())).thenReturn(Optional.of(umlsUser));
+ UmlsUser user = vsacService.verifyUmlsAccess(TEST_API_KEY);
+ when(umlsUserRepository.deleteByHarpId(anyString())).thenReturn(Optional.of(umlsUser));
+ boolean loggedOut = vsacService.logoutUMLSUser(umlsUser.getHarpId());
+ assertThat(user.getHarpId(), is(equalTo(TEST_HARP_ID)));
+ assertThat(user.getApiKey(), is(equalTo(TEST_API_KEY)));
+ assertThat(loggedOut, is(equalTo(true)));
+ }
+
+ @Test
+ void testUserUmlsLogoutUserNotFound() {
+ when(umlsUserRepository.findByHarpId(anyString())).thenReturn(Optional.empty());
+ Exception exception =
+ assertThrows(
+ VsacUnauthorizedException.class, () -> vsacService.logoutUMLSUser(TEST_API_KEY));
+ assertThat(exception.getMessage(), is(equalTo("Please login to UMLS before proceeding")));
+ }
+
+ @Test
+ void testUserUmlsLogoutUserApiKeyIsMissing() {
+ UmlsUser umlsUserCopy = umlsUser.toBuilder().apiKey(null).build();
+ when(umlsUserRepository.findByHarpId(anyString())).thenReturn(Optional.of(umlsUserCopy));
+ Exception exception =
+ assertThrows(
+ VsacUnauthorizedException.class, () -> vsacService.logoutUMLSUser(TEST_API_KEY));
+ assertThat(exception.getMessage(), is(equalTo("Please login to UMLS before proceeding")));
+ }
}
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 6e9bef5..06cc5c2 100644
--- a/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java
+++ b/src/test/java/gov/cms/madie/terminology/webclient/FhirTerminologyServiceWebClientTest.java
@@ -112,7 +112,9 @@ void getDraftValueSetResourceSuccessfully_when_noCustomSearchCriteriaIsProvided(
assertNotNull(actualResponse);
assertEquals(MOCK_RESPONSE_STRING, actualResponse);
RecordedRequest recordedRequest = mockBackEnd.takeRequest();
- assertEquals("/ValueSet/test-vs-id/$expand?includeDraft=true&activeOnly=false", recordedRequest.getPath());
+ assertEquals(
+ "/ValueSet/test-vs-id/$expand?includeDraft=true&activeOnly=false",
+ recordedRequest.getPath());
}
@Test