Skip to content

Commit

Permalink
Fix for accessToken from Message Testing API request. (#17081)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucero-v authored Jan 14, 2025
1 parent 20905dd commit 83a644e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 61 deletions.
16 changes: 6 additions & 10 deletions prime-router/src/main/kotlin/azure/ReportFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.github.ajalt.clikt.core.CliktError
import com.google.common.net.HttpHeaders
import com.microsoft.azure.functions.HttpMethod
import com.microsoft.azure.functions.HttpRequestMessage
import com.microsoft.azure.functions.HttpResponseMessage
Expand Down Expand Up @@ -148,6 +149,8 @@ class ReportFunction(
) request: HttpRequestMessage<String?>,
): HttpResponseMessage {
val claims = AuthenticatedClaims.authenticate(request)
val caseInsensitiveHeaders = request.headers.mapKeys { it.key.lowercase() }
val accessToken = caseInsensitiveHeaders[HttpHeaders.AUTHORIZATION.lowercase()]
if (claims != null && claims.authorized(setOf(Scope.primeAdminScope))) {
val receiverName = request.queryParameters["receiverName"]
val organizationName = request.queryParameters["organizationName"]
Expand Down Expand Up @@ -179,11 +182,12 @@ class ReportFunction(
try {
val result = ProcessFhirCommands().processFhirDataRequest(
file,
Environment.get().envName,
Environment.get(),
receiverName,
organizationName,
senderSchema,
false
false,
accessToken!!
)
file.delete()
val message = if (result.message != null) {
Expand All @@ -202,17 +206,13 @@ class ReportFunction(
MessageOrBundleStringified(
message,
bundle,
result.senderTransformPassed,
result.senderTransformErrors,
result.senderTransformWarnings,
result.enrichmentSchemaPassed,
result.enrichmentSchemaErrors,
result.senderTransformWarnings,
result.receiverTransformPassed,
result.receiverTransformErrors,
result.receiverTransformWarnings,
result.filterErrors,
result.filtersPassed
)
)
)
Expand All @@ -227,17 +227,13 @@ class ReportFunction(
class MessageOrBundleStringified(
var message: String? = null,
var bundle: String? = null,
override var senderTransformPassed: Boolean = true,
override var senderTransformErrors: MutableList<String> = mutableListOf(),
override var senderTransformWarnings: MutableList<String> = mutableListOf(),
override var enrichmentSchemaPassed: Boolean = true,
override var enrichmentSchemaErrors: MutableList<String> = mutableListOf(),
override var enrichmentSchemaWarnings: MutableList<String> = mutableListOf(),
override var receiverTransformPassed: Boolean = true,
override var receiverTransformErrors: MutableList<String> = mutableListOf(),
override var receiverTransformWarnings: MutableList<String> = mutableListOf(),
override var filterErrors: MutableList<String> = mutableListOf(),
override var filtersPassed: Boolean = true,
) : ProcessFhirCommands.MessageOrBundleParent()

/**
Expand Down
64 changes: 37 additions & 27 deletions prime-router/src/main/kotlin/cli/ProcessFhirCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class ProcessFhirCommands : CliktCommand(
private val environmentParam by option(
"--receiver-setting-env", help = "Environment that specifies where to get the receiver settings"
)
.choice("local", "test", "staging", "prod", "demo1")
.default("local", "local environment")

/**
* Sender schema location
Expand All @@ -141,15 +143,39 @@ class ProcessFhirCommands : CliktCommand(

private val hl7DiffHelper = HL7DiffHelper()

/**
* The environment specified by the command line parameters
*/
val environment: Environment by lazy {
Environment.get(environmentParam)
}

/**
* The access token left by a previous login command as specified by the command line parameters
*/
private val oktaAccessToken: String by lazy {

if (environment.oktaApp == null) {
"placeholder_token"
} else {
OktaCommand.fetchAccessToken(environment.oktaApp)
?: abort(
"Invalid access token. " +
"Run ./prime login to fetch/refresh your access token for the $environmentParam environment."
)
}
}

override fun run() {
val messageOrBundle =
processFhirDataRequest(
inputFile,
environmentParam,
environment,
receiverNameParam,
orgNameParam,
senderSchemaParam,
true
true,
oktaAccessToken
)
if (messageOrBundle.message != null) {
outputResult(messageOrBundle.message!!)
Expand All @@ -162,18 +188,19 @@ class ProcessFhirCommands : CliktCommand(

fun processFhirDataRequest(
inputFile: File,
environment: String?,
environment: Environment,
receiverName: String?,
orgName: String?,
senderSchema: String?,
isCli: Boolean,
accessToken: String,
): MessageOrBundle {
// Read the contents of the file
val contents = inputFile.inputStream().readBytes().toString(Charsets.UTF_8)
if (contents.isBlank()) throw CliktError("File ${inputFile.absolutePath} is empty.")
// Check on the extension of the file for supported operations
val inputFileType = inputFile.extension.uppercase()
val receiver = getReceiver(environment, receiverName, orgName, GetMultipleSettings(), isCli)
val receiver = getReceiver(environment, receiverName, orgName, isCli, accessToken)

val messageOrBundle = MessageOrBundle()
when {
Expand Down Expand Up @@ -293,7 +320,6 @@ class ProcessFhirCommands : CliktCommand(

messageOrBundle.bundle = output
}
messageOrBundle.enrichmentSchemaPassed = messageOrBundle.enrichmentSchemaErrors.isEmpty()
}
}

Expand Down Expand Up @@ -350,33 +376,25 @@ class ProcessFhirCommands : CliktCommand(
}

abstract class MessageOrBundleParent(
open var senderTransformPassed: Boolean = true,
open var senderTransformErrors: MutableList<String> = mutableListOf(),
open var senderTransformWarnings: MutableList<String> = mutableListOf(),
open var enrichmentSchemaPassed: Boolean = true,
open var enrichmentSchemaErrors: MutableList<String> = mutableListOf(),
open var enrichmentSchemaWarnings: MutableList<String> = mutableListOf(),
open var receiverTransformPassed: Boolean = true,
open var receiverTransformErrors: MutableList<String> = mutableListOf(),
open var receiverTransformWarnings: MutableList<String> = mutableListOf(),
open var filterErrors: MutableList<String> = mutableListOf(),
open var filtersPassed: Boolean = true,
)

class MessageOrBundle(
var message: Message? = null,
var bundle: Bundle? = null,
override var senderTransformPassed: Boolean = true,
override var senderTransformErrors: MutableList<String> = mutableListOf(),
override var senderTransformWarnings: MutableList<String> = mutableListOf(),
override var enrichmentSchemaPassed: Boolean = true,
override var enrichmentSchemaErrors: MutableList<String> = mutableListOf(),
override var enrichmentSchemaWarnings: MutableList<String> = mutableListOf(),
override var receiverTransformPassed: Boolean = true,
override var receiverTransformErrors: MutableList<String> = mutableListOf(),
override var receiverTransformWarnings: MutableList<String> = mutableListOf(),
override var filterErrors: MutableList<String> = mutableListOf(),
override var filtersPassed: Boolean = true,
) : MessageOrBundleParent()

private fun applyConditionFilter(receiver: Receiver, bundle: Bundle): Bundle {
Expand Down Expand Up @@ -404,27 +422,20 @@ class ProcessFhirCommands : CliktCommand(
}

fun getReceiver(
environment: String?,
environment: Environment,
receiverName: String?,
orgName: String?,
getMultipleSettings: GetMultipleSettings = GetMultipleSettings(),
isCli: Boolean,
accessToken: String,
): Receiver? {
if (!environment.isNullOrBlank() && !receiverName.isNullOrBlank() && !orgName.isNullOrBlank()) {
if (!receiverName.isNullOrBlank() && !orgName.isNullOrBlank()) {
if (isCli && !outputFormat.isNullOrBlank()) {
throw CliktError(
"Please specify either a receiver OR an output format. Not both."
)
}
val foundEnvironment = Environment.get(environment)
val accessToken = OktaCommand.fetchAccessToken(foundEnvironment.oktaApp)
?: abort(
"Invalid access token. " +
"Run ./prime login to fetch/refresh your access " +
"token for the $foundEnvironment environment."
)
val organizations = getMultipleSettings.getAll(
environment = foundEnvironment,
val organizations = GetMultipleSettings().getAll(
environment = environment,
accessToken = accessToken,
specificOrg = orgName,
exactMatch = true
Expand All @@ -439,7 +450,7 @@ class ProcessFhirCommands : CliktCommand(
}
} else if (isCli && outputFormat.isNullOrBlank()) {
throw CliktError(
"Output format is required if the environment, receiver, and org " +
"Output format is required if the receiver and org " +
"are not specified. "
)
}
Expand Down Expand Up @@ -491,7 +502,6 @@ class ProcessFhirCommands : CliktCommand(
errors = messageOrBundle.receiverTransformErrors
).process(messageOrBundle.bundle!!)
messageOrBundle.message = message
messageOrBundle.receiverTransformPassed = messageOrBundle.receiverTransformErrors.isEmpty()
}
}

Expand Down
2 changes: 1 addition & 1 deletion prime-router/src/main/kotlin/cli/SettingCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ class GetMultipleSettings : SettingCommand(

fun getAll(
environment: Environment,
accessToken: String = oktaAccessToken,
accessToken: String,
specificOrg: String? = filter,
exactMatch: Boolean = false,
): List<DeepOrganization> {
Expand Down
47 changes: 24 additions & 23 deletions prime-router/src/test/kotlin/azure/ReportFunctionTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import gov.cdc.prime.router.azure.db.enums.TaskAction
import gov.cdc.prime.router.azure.db.tables.pojos.Action
import gov.cdc.prime.router.azure.db.tables.pojos.ReportFile
import gov.cdc.prime.router.azure.observability.event.ReportStreamEventService
import gov.cdc.prime.router.cli.GetMultipleSettings
import gov.cdc.prime.router.cli.PIIRemovalCommands
import gov.cdc.prime.router.cli.ProcessFhirCommands
import gov.cdc.prime.router.common.Environment
import gov.cdc.prime.router.history.DetailedSubmissionHistory
import gov.cdc.prime.router.history.azure.SubmissionsFacade
import gov.cdc.prime.router.serializers.Hl7Serializer
Expand Down Expand Up @@ -1103,33 +1103,51 @@ class ReportFunctionTests {
assertThrows<CliktError> {
ProcessFhirCommands().processFhirDataRequest(
file,
"local",
Environment.get("staging"),
"full-elr",
"me-phd",
"classpath:/metadata/fhir_transforms/senders/SimpleReport/simple-report-sender-transform.yml",
false
false,
""
)
}
file.delete()
}

@Test
fun `processFhirDataRequest no environment, receiver name, or org name and output format blank`() {
fun `processFhirDataRequest receiver name, or org name and output format blank`() {
val file = File("filename.txt")
file.createNewFile()
assertThrows<CliktError> {
ProcessFhirCommands().processFhirDataRequest(
file,
"",
Environment.get("local"),
"",
"",
"classpath:/metadata/fhir_transforms/senders/SimpleReport/simple-report-sender-transform.yml",
false
false,
""
)
}
file.delete()
}

@Test
fun `processFhirDataRequest nonCLI request in staging without access token should fail`() {
val file = File("src/testIntegration/resources/datatests/FHIR_to_HL7/sample_ME_20240806-0001.fhir")
assertThrows<CliktError> {
ProcessFhirCommands().processFhirDataRequest(
file,
Environment.get("staging"),
"full-elr",
"me-phd",
"classpath:/metadata/fhir_transforms/senders/SimpleReport/simple-report-sender-transform.yml",
false,
""
)
}
}

@Suppress("ktlint:standard:max-line-length")
val jurisdictionalFilter: ReportStreamFilter =
listOf("(Bundle.entry.resource.ofType(ServiceRequest)[0].requester.resolve().organization.resolve().address.state = 'ME') or (Bundle.entry.resource.ofType(Patient).address.state = 'ME')")
Expand Down Expand Up @@ -1190,23 +1208,6 @@ class ReportFunctionTests {
qualityFilter
)

@Test
fun getReceiver() {
val file = File("filename.txt")
file.createNewFile()
val getMultipleSettings = mockkClass(GetMultipleSettings::class)
every { getMultipleSettings.getAll(any(), any(), "me-phd", true) } returns
listOf(DeepOrganization(organization, listOf(sender), listOf(receiver)))
val receiverReturned = ProcessFhirCommands().getReceiver(
"local",
"full-elr",
"me-phd",
getMultipleSettings,
false
)
assert(receiverReturned!!.name == receiver.name)
}

@Test
fun `return ack if requested and enabled`() {
val mockEngine = mockk<WorkflowEngine>()
Expand Down

0 comments on commit 83a644e

Please sign in to comment.