Smile CDR v2024.05.PRE
On this page:

15.14.1Consent Service: Java API

 

To use the Consent Service Java API, you must provide an implementation of the IConsentService interface, as described in the HAPI FHIR ConsentInterceptor documentation.

Consent Service implementation classes may access details about the request context from the RequestDetails object, using the attributes described in Security Attributes.

15.14.2Example

 

The following example shows a Java consent service implementation.

A complete project containing this example is available in the Interceptor Starter Project.

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2024 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */
package com.smilecdr.demo.consent;

import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Observation;

import java.util.Set;

/**
 * This class is an example of a Java Consent Service implementation.
 * <p>
 * This consent service tests whether the client session has the
 * approved scope "observation_view_covid19", and filters Observation
 * resources matching the LOINC code "94767-1" if not.
 */
public class ScopeDrivenConsentService implements IConsentService {

   @Override
   public ConsentOutcome canSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {

      // This example consent service only cares about resources of type
      // Observation, so accept any others automatically. For separation
      // of concerns, you might choose to add additional consent service
      // implementations that handle other resource types, or you could
      // add additional logic here.
      if (!(theResource instanceof Observation)) {
         return ConsentOutcome.PROCEED;
      }

      Observation obs = (Observation) theResource;
      String resourceSystem = obs.getCode().getCodingFirstRep().getSystem();
      String resourceCode = obs.getCode().getCodingFirstRep().getCode();

      // Any non-LOINC coded Observations will be filtered out
      if (!"http://loinc.org".equals(resourceSystem)) {
         return ConsentOutcome.REJECT;
      }

      // The LOINC code 94767-1 corresponds to a SARS-COV-2 Serum/Plasma test. Unless the session
      // has an appropriate scope approved, we'll filter this result.
      if (resourceCode.equals("94767-1")) {
         Set<String> approvedScopes = (Set<String>) theRequestDetails.getAttribute("ca.cdr.servletattribute.session.oidc.approved_scopes");
         if (!approvedScopes.contains("observation_view_covid19")) {
            return ConsentOutcome.REJECT;
         }
      }

      // Any other resources are authorized, meaning that the client will get
      // to see the resources, and consentWillSeeResource(...) is not called. This
      // is good for performance but means that no filtering can take place.
      return ConsentOutcome.PROCEED;
   }
}