Skip to content

Commit 3805918

Browse files
committed
BFD-3666 stringutil method to get a boolean value include the certificate check
1 parent d1e1ed3 commit 3805918

File tree

6 files changed

+193
-78
lines changed

6 files changed

+193
-78
lines changed

apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/V1SamhsaConsentInterceptor.java

+14-32
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package gov.cms.bfd.server.war;
22

3+
import static gov.cms.bfd.server.war.commons.StringUtils.parseBoolean;
4+
35
import ca.uhn.fhir.rest.api.server.RequestDetails;
46
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
57
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
68
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
79
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
8-
import java.util.Optional;
10+
import gov.cms.bfd.server.war.commons.CommonTransformerUtils;
11+
import gov.cms.bfd.sharedutils.TagCode;
912
import org.hl7.fhir.dstu3.model.Bundle;
1013
import org.hl7.fhir.dstu3.model.Coding;
1114
import org.hl7.fhir.dstu3.model.ExplanationOfBenefit;
@@ -20,18 +23,6 @@ public class V1SamhsaConsentInterceptor implements IConsentService {
2023
/** The logger. */
2124
private static final Logger logger = LoggerFactory.getLogger(V1SamhsaConsentInterceptor.class);
2225

23-
/** Flag to control whether SAMHSA filtering should be applied. */
24-
private final boolean samhsaV2Enabled;
25-
26-
/**
27-
* SamhsaConsentInterceptor Constructor.
28-
*
29-
* @param samhsaV2Enabled samhsaV2Enabled
30-
*/
31-
public V1SamhsaConsentInterceptor(Boolean samhsaV2Enabled) {
32-
this.samhsaV2Enabled = samhsaV2Enabled;
33-
}
34-
3526
@Override
3627
public ConsentOutcome startOperation(
3728
RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
@@ -45,29 +36,19 @@ public ConsentOutcome willSeeResource(
4536
IConsentContextServices theContextServices) {
4637

4738
logger.info("V1SamhsaConsentInterceptor - willSeeResource.");
48-
// Check if SAMHSA 2.0 filtering is enabled
49-
if (!samhsaV2Enabled) {
50-
// If the feature flag is false, skip filtering and proceed with the resource
51-
logger.info("SAMHSA 2.0 filtering is disabled, proceeding without filtering.");
52-
return ConsentOutcome.PROCEED;
53-
}
5439

5540
// Extract 'excludeSAMHSA' parameter from the request URL
56-
boolean excludeSamhsa =
57-
Optional.ofNullable(theRequestDetails.getParameters().get("excludeSAMHSA"))
58-
.flatMap(params -> params.length > 0 ? Optional.of(params[0]) : Optional.empty())
59-
.map(Boolean::parseBoolean)
60-
.orElse(false);
41+
boolean excludeSAMHSA = parseBoolean(theRequestDetails.getParameters().get("excludeSAMHSA"));
42+
boolean filterSamhsa =
43+
CommonTransformerUtils.shouldFilterSamhsa(String.valueOf(excludeSAMHSA), theRequestDetails);
6144

6245
// Handle Bundle
63-
if (theResource instanceof Bundle) {
64-
Bundle bundle = (Bundle) theResource;
65-
46+
if (theResource instanceof Bundle bundle) {
6647
// Iterate through each entry in the Bundle
6748
for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
6849
IBaseResource entryResource = entry.getResource();
6950

70-
if (shouldRedactResource(entryResource, excludeSamhsa)) {
51+
if (shouldRedactResource(entryResource, filterSamhsa)) {
7152
redactSensitiveData(entry);
7253
}
7354
}
@@ -80,10 +61,10 @@ public ConsentOutcome willSeeResource(
8061
* Helper method to determine if a resource should be redacted based on security tags.
8162
*
8263
* @param resource The resource to check.
83-
* @param excludeSamhsa Flag to determine whether to exclude SAMHSA.
64+
* @param filterSamhsa Flag to determine whether to filter SAMHSA.
8465
* @return true if the resource should be redacted, false otherwise.
8566
*/
86-
private boolean shouldRedactResource(IBaseResource resource, boolean excludeSamhsa) {
67+
private boolean shouldRedactResource(IBaseResource resource, boolean filterSamhsa) {
8768
Meta meta = null;
8869

8970
// Extract the meta information depending on the resource type
@@ -99,8 +80,9 @@ private boolean shouldRedactResource(IBaseResource resource, boolean excludeSamh
9980
// Iterate through the security tags in the meta
10081
for (Coding securityTag : meta.getSecurity()) {
10182
// Check if the security tag matches the "R" or "42CFRPart2" code
102-
if (excludeSamhsa
103-
&& ("R".equals(securityTag.getCode()) || "42CFRPart2".equals(securityTag.getCode()))) {
83+
if (filterSamhsa
84+
&& (TagCode.R.name().equals(securityTag.getCode())
85+
|| TagCode._42CFRPart2.name().equals(securityTag.getCode()))) {
10486
logger.info("Matched SAMHSA security tag, redacting resource.");
10587
return true;
10688
}

apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/V1Server.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ protected void initialize() throws ServletException {
132132
// executed
133133
registerInterceptor(new TimerInterceptor());
134134
if (samhsaV2Enabled) {
135-
registerInterceptor(new ConsentInterceptor(new V1SamhsaConsentInterceptor(samhsaV2Enabled)));
135+
registerInterceptor(new ConsentInterceptor(new V1SamhsaConsentInterceptor()));
136136
}
137137
// OpenAPI
138138
OpenApiInterceptor openApiInterceptor = new OpenApiInterceptor();

apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/V2SamhsaConsentInterceptor.java

+18-44
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
package gov.cms.bfd.server.war;
22

3+
import static gov.cms.bfd.server.war.commons.StringUtils.parseBoolean;
4+
35
import ca.uhn.fhir.rest.api.server.RequestDetails;
46
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
57
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
68
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
79
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
8-
import java.util.Optional;
10+
import gov.cms.bfd.server.war.commons.CommonTransformerUtils;
11+
import gov.cms.bfd.sharedutils.TagCode;
912
import org.hl7.fhir.instance.model.api.IBaseCoding;
1013
import org.hl7.fhir.instance.model.api.IBaseResource;
1114
import org.hl7.fhir.r4.model.Bundle;
12-
import org.hl7.fhir.r4.model.Claim;
13-
import org.hl7.fhir.r4.model.ClaimResponse;
14-
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
1515
import org.hl7.fhir.r4.model.Meta;
16+
import org.hl7.fhir.r4.model.Resource;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
1819

@@ -26,18 +27,6 @@ public class V2SamhsaConsentInterceptor implements IConsentService {
2627
/** The logger. */
2728
private static final Logger logger = LoggerFactory.getLogger(V2SamhsaConsentInterceptor.class);
2829

29-
/** Flag to control whether SAMHSA filtering should be applied. */
30-
private final boolean samhsaV2Enabled;
31-
32-
/**
33-
* SamhsaConsentInterceptor Constructor.
34-
*
35-
* @param samhsaV2Enabled samhsaV2Enabled
36-
*/
37-
public V2SamhsaConsentInterceptor(Boolean samhsaV2Enabled) {
38-
this.samhsaV2Enabled = samhsaV2Enabled;
39-
}
40-
4130
/**
4231
* Invoked once at the start of every request.
4332
*
@@ -65,29 +54,18 @@ public ConsentOutcome willSeeResource(
6554

6655
logger.info("SAMHSAConsentInterceptor - willSeeResource.");
6756

68-
// Check if SAMHSA 2.0 filtering is enabled
69-
if (!samhsaV2Enabled) {
70-
// If the feature flag is false, skip filtering and proceed with the resource
71-
logger.info("SAMHSA 2.0 filtering is disabled, proceeding without filtering.");
72-
return ConsentOutcome.PROCEED;
73-
}
74-
7557
// Extract 'excludeSAMHSA' parameter from the request URL
76-
boolean excludeSamhsa =
77-
Optional.ofNullable(theRequestDetails.getParameters().get("excludeSAMHSA"))
78-
.flatMap(params -> params.length > 0 ? Optional.of(params[0]) : Optional.empty())
79-
.map(Boolean::parseBoolean)
80-
.orElse(false);
58+
boolean excludeSamhsa = parseBoolean(theRequestDetails.getParameters().get("excludeSAMHSA"));
59+
boolean filterSamhsa =
60+
CommonTransformerUtils.shouldFilterSamhsa(String.valueOf(excludeSamhsa), theRequestDetails);
8161

8262
// Check if the resource is a Bundle and if it has entries
83-
if (theResource instanceof Bundle) {
84-
Bundle bundle = (Bundle) theResource;
85-
63+
if (theResource instanceof Bundle bundle) {
8664
// Iterate through each entry in the Bundle
8765
for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
8866
IBaseResource entryResource = entry.getResource();
8967

90-
if (shouldRedactResource(entryResource, excludeSamhsa)) {
68+
if (shouldRedactResource(entryResource, filterSamhsa)) {
9169
redactSensitiveData(entry);
9270
}
9371
}
@@ -100,19 +78,14 @@ public ConsentOutcome willSeeResource(
10078
/**
10179
* Helper method to determine if a resource should be redacted based on security tags.
10280
*
103-
* @param resource The resource to check.
104-
* @param excludeSamhsa Flag to determine whether to exclude SAMHSA.
81+
* @param baseResource The resource to check.
82+
* @param filterSamhsa Flag to determine whether to filter SAMHSA.
10583
* @return true if the resource should be redacted, false otherwise.
10684
*/
107-
private boolean shouldRedactResource(IBaseResource resource, boolean excludeSamhsa) {
108-
85+
private boolean shouldRedactResource(IBaseResource baseResource, boolean filterSamhsa) {
10986
Meta meta = null;
110-
if (resource instanceof Claim) {
111-
meta = ((Claim) resource).getMeta();
112-
} else if (resource instanceof ClaimResponse) {
113-
meta = ((ClaimResponse) resource).getMeta();
114-
} else if (resource instanceof ExplanationOfBenefit) {
115-
meta = ((ExplanationOfBenefit) resource).getMeta();
87+
if (baseResource instanceof Resource resource) {
88+
meta = resource.getMeta();
11689
}
11790
// If meta or security tags are not present, no need to redact
11891
if (meta == null || meta.getSecurity() == null) {
@@ -122,8 +95,9 @@ private boolean shouldRedactResource(IBaseResource resource, boolean excludeSamh
12295
// Iterate through the security tags in the meta
12396
for (IBaseCoding securityTag : meta.getSecurity()) {
12497
// Check if the security tag matches the "R" or "42CFRPart2" code
125-
if (excludeSamhsa
126-
&& ("R".equals(securityTag.getCode()) || "42CFRPart2".equals(securityTag.getCode()))) {
98+
if (filterSamhsa
99+
&& (TagCode.R.name().equals(securityTag.getCode())
100+
|| TagCode._42CFRPart2.name().equals(securityTag.getCode()))) {
127101
logger.info("Matched SAMHSA security tag, redacting resource.");
128102
return true;
129103
}

apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/V2Server.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ protected void initialize() throws ServletException {
132132
// executed
133133
registerInterceptor(new TimerInterceptor());
134134
if (samhsaV2Enabled) {
135-
registerInterceptor(new ConsentInterceptor(new V2SamhsaConsentInterceptor(samhsaV2Enabled)));
135+
registerInterceptor(new ConsentInterceptor(new V2SamhsaConsentInterceptor()));
136136
}
137137
// OpenAPI
138138
OpenApiInterceptor openApiInterceptor = new OpenApiInterceptor();

apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/commons/StringUtils.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package gov.cms.bfd.server.war.commons;
22

33
import com.google.common.collect.ImmutableList;
4+
import java.util.Optional;
45

56
/** Helper Utils class for Functions shared across. multiple classes. */
67
public class StringUtils {
@@ -31,4 +32,18 @@ public static String[] splitOnCommas(String input) {
3132
}
3233
return builder.build().toArray(new String[0]);
3334
}
35+
36+
/**
37+
* Custom function to retrieve the boolean value from a string input.
38+
*
39+
* @param input a String that needs to remove whitespace and commas.
40+
* @return Split Array.
41+
*/
42+
public static Boolean parseBoolean(String[] input) {
43+
44+
return Optional.ofNullable(input)
45+
.flatMap(params -> params.length > 0 ? Optional.of(params[0]) : Optional.empty())
46+
.map(Boolean::parseBoolean)
47+
.orElse(false);
48+
}
3449
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// package gov.cms.bfd.server.war;
2+
//
3+
// import static org.junit.Assert.*;
4+
// import static org.mockito.Mockito.*;
5+
//
6+
// import ca.uhn.fhir.rest.api.server.RequestDetails;
7+
// import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
8+
// import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
9+
// import java.util.Collections;
10+
// import org.hl7.fhir.instance.model.api.IBaseResource;
11+
// import org.hl7.fhir.r4.model.Bundle;
12+
// import org.hl7.fhir.r4.model.Claim;
13+
// import org.hl7.fhir.r4.model.Meta;
14+
// import org.junit.Before;
15+
// import org.junit.Test;
16+
// import org.mockito.*;
17+
//
18+
// public class V2SamhsaConsentInterceptorTest {
19+
//
20+
// @Mock private RequestDetails requestDetails;
21+
//
22+
// @Mock private IConsentContextServices contextServices;
23+
//
24+
// @Mock private IBaseResource claimResource;
25+
//
26+
// @Mock private Bundle bundle;
27+
//
28+
// @Mock private V2SamhsaConsentInterceptor v2SamhsaConsentInterceptor;
29+
//
30+
// @Before
31+
// public void setUp() {
32+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(false);
33+
// MockitoAnnotations.openMocks(this);
34+
// }
35+
//
36+
// @Test
37+
// public void testWillSeeResource_whenSamhsaV2EnabledAndExcludeSAMHSAFalse() {
38+
// // Test with SAMHSA filtering enabled and "excludeSAMHSA" flag set to false
39+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(true);
40+
//
41+
// when(requestDetails.getParameters()).thenReturn(Collections.emptyMap());
42+
// when(claimResource.getMeta()).thenReturn(new Meta());
43+
//
44+
// ConsentOutcome outcome =
45+
// v2SamhsaConsentInterceptor.willSeeResource(requestDetails, claimResource,
46+
// contextServices);
47+
//
48+
// assertEquals(ConsentOutcome.PROCEED, outcome);
49+
// }
50+
//
51+
// @Test
52+
// public void testWillSeeResource_whenSamhsaV2Disabled() {
53+
// // Test with SAMHSA filtering disabled
54+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(false);
55+
//
56+
// when(requestDetails.getParameters()).thenReturn(Collections.emptyMap());
57+
//
58+
// ConsentOutcome outcome =
59+
// v2SamhsaConsentInterceptor.willSeeResource(requestDetails, claimResource,
60+
// contextServices);
61+
//
62+
// assertEquals(ConsentOutcome.PROCEED, outcome);
63+
// }
64+
//
65+
// @Test
66+
// public void testWillSeeResource_whenSamhsaV2EnabledAndMatchingSAMHSA() {
67+
// // Test with SAMHSA filtering enabled and a resource having matching SAMHSA tag
68+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(true);
69+
//
70+
// // Setup request with "excludeSAMHSA" set to true
71+
// when(requestDetails.getParameters())
72+
// .thenReturn(Collections.singletonMap("excludeSAMHSA", new String[] {"true"}));
73+
//
74+
// // Mock a Claim resource with a SAMHSA tag
75+
// Claim claim = new Claim();
76+
// Meta meta = new Meta();
77+
// claim.setMeta(meta);
78+
//
79+
// // Add SAMHSA tag ("42CFRPart2")
80+
// meta.addSecurity().setCode("42CFRPart2");
81+
//
82+
// // Mock the Bundle entry to contain this claim resource
83+
// Bundle.BundleEntryComponent entry = mock(Bundle.BundleEntryComponent.class);
84+
// when(entry.getResource()).thenReturn(claim);
85+
//
86+
// // Mock the Bundle to contain the entry
87+
// when(bundle.getEntry()).thenReturn(Collections.singletonList(entry));
88+
//
89+
// // Call willSeeResource with the Bundle containing the claim
90+
// ConsentOutcome outcome =
91+
// v2SamhsaConsentInterceptor.willSeeResource(requestDetails, bundle, contextServices);
92+
//
93+
// // Assert that the outcome is PROCEED (or any other expected outcome)
94+
// assertEquals(ConsentOutcome.PROCEED, outcome);
95+
// }
96+
//
97+
// // @Test
98+
// // public void testRedactSensitiveData() {
99+
// // // Test the redactSensitiveData method by mocking a resource
100+
// // Bundle.BundleEntryComponent entryComponent = mock(Bundle.BundleEntryComponent.class);
101+
// // Claim claim = mock(Claim.class);
102+
// //
103+
// // when(entryComponent.getResource()).thenReturn(claim);
104+
// //
105+
// // // Test that redaction happens
106+
// // v2SamhsaConsentInterceptor.redactSensitiveData(entryComponent);
107+
// //
108+
// // verify(v2SamhsaConsentInterceptor, times(1)).redactSensitiveData(any());
109+
// // }
110+
//
111+
// @Test
112+
// public void testStartOperation() {
113+
// // Test startOperation method
114+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(true);
115+
//
116+
// ConsentOutcome outcome =
117+
// v2SamhsaConsentInterceptor.startOperation(requestDetails, contextServices);
118+
//
119+
// assertEquals(ConsentOutcome.PROCEED, outcome);
120+
// }
121+
//
122+
// @Test
123+
// public void testCompleteOperationSuccess() {
124+
// // Test completeOperationSuccess method
125+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(true);
126+
//
127+
// v2SamhsaConsentInterceptor.completeOperationSuccess(requestDetails, contextServices);
128+
//
129+
// // Ensure no exceptions, logging, or errors happen
130+
// }
131+
//
132+
// @Test
133+
// public void testCompleteOperationFailure() {
134+
// // Test completeOperationFailure method
135+
// v2SamhsaConsentInterceptor = new V2SamhsaConsentInterceptor(true);
136+
//
137+
// BaseServerResponseException exception = mock(BaseServerResponseException.class);
138+
//
139+
// v2SamhsaConsentInterceptor.completeOperationFailure(requestDetails, exception,
140+
// contextServices);
141+
//
142+
// // Ensure no exceptions, logging, or errors happen
143+
// }
144+
// }

0 commit comments

Comments
 (0)