libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 7fb10e97704f964d3338fb9ebb9dc5cc3e63cf80
parent 1f70330aa38dc80e188cfc4b991aa19c15aef485
Author: MS <ms@taler.net>
Date:   Wed, 23 Nov 2022 19:57:10 +0100

debug

Diffstat:
A.idea/libeufin.iml | 14++++++++++++++
A.idea/runConfigurations/SchedulingTest.xml | 22++++++++++++++++++++++
Mnexus/build.gradle | 2++
Mnexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt | 4++--
Mnexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt | 5++++-
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 20++++++++++----------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 4+++-
7 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/.idea/libeufin.iml b/.idea/libeufin.iml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module external.linked.project.id="libeufin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.0.1-dev.3" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_16" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <excludeFolder url="file://$MODULE_DIR$/.gradle" /> + <excludeFolder url="file://$MODULE_DIR$/build" /> + <excludeFolder url="file://$MODULE_DIR$/frontend" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> +\ No newline at end of file diff --git a/.idea/runConfigurations/SchedulingTest.xml b/.idea/runConfigurations/SchedulingTest.xml @@ -0,0 +1,21 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="SchedulingTest" type="GradleRunConfiguration" factoryName="Gradle"> + <ExternalSystemSettings> + <option name="executionName" /> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="externalSystemIdString" value="GRADLE" /> + <option name="scriptParameters" value=":nexus:test --tests --quiet &quot;SchedulingTest&quot;" /> + <option name="taskDescriptions"> + <list /> + </option> + <option name="taskNames"> + <list /> + </option> + <option name="vmOptions" /> + </ExternalSystemSettings> + <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess> + <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> + <DebugAllEnabled>false</DebugAllEnabled> + <method v="2" /> + </configuration> +</component> +\ No newline at end of file diff --git a/nexus/build.gradle b/nexus/build.gradle @@ -61,6 +61,7 @@ dependencies { // LibEuFin util library implementation project(":util") + implementation project(":sandbox") // for testing // Logging implementation 'ch.qos.logback:logback-classic:1.2.5' @@ -89,6 +90,7 @@ dependencies { implementation "io.ktor:ktor-server-core:$ktor_version" implementation "io.ktor:ktor-client-apache:$ktor_version" implementation "io.ktor:ktor-server-netty:$ktor_version" + implementation "io.ktor:ktor-server-test-host:$ktor_version" implementation "io.ktor:ktor-auth:$ktor_version" implementation "io.ktor:ktor-jackson:$ktor_version" diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Scheduling.kt @@ -60,11 +60,11 @@ private suspend fun runTask(client: HttpClient, sched: TaskSchedule) { submitAllPaymentInitiations(client, sched.resourceId) } else -> { - logger.error("task type ${sched.type} not understood") + logger.error("task type ${sched.type} not supported") } } } - else -> logger.error("task on resource ${sched.resourceType} not understood") + else -> logger.error("task on resource ${sched.resourceType} not supported") } } catch (e: Exception) { logger.error("Exception during task $sched", e) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt @@ -187,7 +187,10 @@ suspend fun doEbicsDownloadTransaction( EbicsReturnCode.EBICS_DOWNLOAD_POSTPROCESS_DONE -> { } else -> { - throw NexusError(HttpStatusCode.InternalServerError, "unexpected return code") + throw NexusError( + HttpStatusCode.InternalServerError, + "unexpected return code: ${ackResponse.technicalReturnCode.name}" + ) } } return EbicsDownloadSuccessResult(respPayload) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -34,7 +34,6 @@ import org.jetbrains.exposed.exceptions.ExposedSQLException import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.statements.api.ExposedBlob -import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.transaction import org.w3c.dom.Document import tech.libeufin.util.* @@ -152,8 +151,8 @@ suspend fun respondEbicsTransfer( EbicsHostsTable.hostID.upperCase() eq call.attributes[EbicsHostIdAttribute] .uppercase() }.firstOrNull() ?: throw SandboxError( - io.ktor.http.HttpStatusCode.InternalServerError, - "Requested Ebics host ID not found." + HttpStatusCode.InternalServerError, + "Requested Ebics host ID (${call.attributes[EbicsHostIdAttribute]}) not found." ) CryptoUtil.loadRsaPrivateKey(host.authenticationPrivateKey.bytes) } @@ -1123,7 +1122,9 @@ private fun handleEbicsDownloadTransactionTransfer(requestContext: RequestContex ) } - +/** + * + */ private fun handleEbicsDownloadTransactionInitialization(requestContext: RequestContext): EbicsResponse { val orderType = requestContext.requestObject.header.static.orderDetails?.orderType ?: throw EbicsInvalidRequestError() @@ -1149,6 +1150,10 @@ private fun handleEbicsDownloadTransactionInitialization(requestContext: Request val totalSize = encodedResponse.length val numSegments = ((totalSize + segmentSize - 1) / segmentSize) + /** + * Clarify: the encoded response seems to be returned here + * (init phase) AND along the transfer phase. + */ EbicsDownloadTransactionEntity.new(transactionID) { this.subscriber = requestContext.subscriber this.host = requestContext.ebicsHost @@ -1163,7 +1168,7 @@ private fun handleEbicsDownloadTransactionInitialization(requestContext: Request transactionID, numSegments, segmentSize, - enc, + enc, // has customer key encodedResponse ) } @@ -1287,7 +1292,6 @@ private fun makeRequestContext(requestObject: EbicsRequest): RequestContext { var downloadTransaction: EbicsDownloadTransactionEntity? = null var uploadTransaction: EbicsUploadTransactionEntity? = null val subscriber = if (requestTransactionID != null) { - // println("finding subscriber by transactionID $requestTransactionID") downloadTransaction = EbicsDownloadTransactionEntity.findById(requestTransactionID.uppercase(Locale.getDefault())) if (downloadTransaction != null) { downloadTransaction.subscriber @@ -1344,8 +1348,6 @@ suspend fun ApplicationCall.ebicsweb() { EbicsHostIdAttribute, requestedHostID.item(0).textContent ) - // val requestDocument = receiveEbicsXml() - // logger.info("Processing ${requestDocument.documentElement.localName}") when (requestDocument.documentElement.localName) { "ebicsUnsecuredRequest" -> { val requestObject = requestDocument.toObject<EbicsUnsecuredRequest>() @@ -1370,7 +1372,6 @@ suspend fun ApplicationCall.ebicsweb() { } val strResp = XMLUtil.convertJaxbToString(hevResponse) - logger.debug("HEV response: $strResp") if (!XMLUtil.validateFromString(strResp)) throw SandboxError( HttpStatusCode.InternalServerError, "Outgoing HEV response is invalid" @@ -1386,7 +1387,6 @@ suspend fun ApplicationCall.ebicsweb() { } } "ebicsRequest" -> { - // logger.debug("ebicsRequest ${XMLUtil.convertDomToString(requestDocument)}") val requestObject = requestDocument.toObject<EbicsRequest>() val responseXmlStr = transaction(Connection.TRANSACTION_SERIALIZABLE, repetitionAttempts = 10) { // Step 1 of 3: Get information about the host and subscriber diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -92,7 +92,7 @@ data class SandboxError( val statusCode: HttpStatusCode, val reason: String, val errorCode: LibeufinErrorCode? = null -) : Exception() +) : Exception(reason) data class SandboxErrorJson(val error: SandboxErrorDetailJson) data class SandboxErrorDetailJson(val type: String, val description: String) @@ -975,6 +975,8 @@ val sandboxApp: Application.() -> Unit = { throw EbicsProcessingError("Serving EBICS threw unmanaged UtilError: ${e.reason}") } catch (e: SandboxError) { + val payload: String = e.message ?: e.stackTraceToString() + logger.info(payload) // Should translate to EBICS error code. when (e.errorCode) { LibeufinErrorCode.LIBEUFIN_EC_INVALID_STATE -> throw EbicsProcessingError("Invalid bank state.")