[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (1f70330a -> 39ece551)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (1f70330a -> 39ece551) |
Date: |
Wed, 23 Nov 2022 20:06:16 +0100 |
This is an automated email from the git hooks/post-receive script.
ms pushed a change to branch master
in repository libeufin.
from 1f70330a comments, var renaming
new 7fb10e97 debug
new 79ab57d2 remove newline
new 0b14b8f0 Nexus tests.
new c05b1eb6 comment
new 52d5b56c moving code
new 39ece551 EBICS payload prepare helper.
The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.idea/libeufin.iml | 13 ++
.../{test_sandbox.xml => SchedulingTest.xml} | 14 +-
nexus/build.gradle | 2 +
.../main/kotlin/tech/libeufin/nexus/Scheduling.kt | 4 +-
.../tech/libeufin/nexus/ebics/EbicsClient.kt | 5 +-
.../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt | 1 -
nexus/src/test/kotlin/DBTest.kt | 26 +---
nexus/src/test/kotlin/MakeEnv.kt | 171 +++++++++++++++++++++
nexus/src/test/kotlin/SchedulingTest.kt | 140 +++++++++++++++++
nexus/src/test/kotlin/SelfContainedDBTest.kt | 24 ---
.../resources/logback-test.xml} | 5 +
.../tech/libeufin/sandbox/EbicsProtocolBackend.kt | 20 +--
.../main/kotlin/tech/libeufin/sandbox/Helpers.kt | 29 +++-
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 4 +-
14 files changed, 384 insertions(+), 74 deletions(-)
create mode 100644 .idea/libeufin.iml
copy .idea/runConfigurations/{test_sandbox.xml => SchedulingTest.xml} (51%)
create mode 100644 nexus/src/test/kotlin/MakeEnv.kt
create mode 100644 nexus/src/test/kotlin/SchedulingTest.kt
copy nexus/src/{main/resources/logback.xml => test/resources/logback-test.xml}
(80%)
diff --git a/.idea/libeufin.iml b/.idea/libeufin.iml
new file mode 100644
index 00000000..186d698a
--- /dev/null
+++ 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/test_sandbox.xml
b/.idea/runConfigurations/SchedulingTest.xml
similarity index 51%
copy from .idea/runConfigurations/test_sandbox.xml
copy to .idea/runConfigurations/SchedulingTest.xml
index 2bd23e79..6b78179c 100644
--- a/.idea/runConfigurations/test_sandbox.xml
+++ b/.idea/runConfigurations/SchedulingTest.xml
@@ -1,21 +1,19 @@
<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="test-sandbox"
type="GradleRunConfiguration" factoryName="Gradle"
show_console_on_std_out="true">
+ <configuration default="false" name="SchedulingTest"
type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
- <option name="externalProjectPath" value="$PROJECT_DIR$/sandbox" />
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
- <option name="scriptParameters" value="--info" />
+ <option name="scriptParameters" value=":nexus:test --tests --quiet
"SchedulingTest"" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
- <list>
- <option value="test" />
- </list>
+ <list />
</option>
- <option name="vmOptions" value="" />
+ <option name="vmOptions" />
</ExternalSystemSettings>
- <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
+ <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
diff --git a/nexus/build.gradle b/nexus/build.gradle
index 4d4f9041..e5a0affb 100644
--- 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
index 09c4bcc2..ffcbe43c 100644
--- 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
index 281410d5..e5c78434 100644
--- 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/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
index a5371599..3d72fcb8 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -664,7 +664,6 @@ class EbicsBankConnectionProtocol: BankConnectionProtocol {
node.set<JsonNode>("details", details)
return node
}
-
override fun createConnection(connId: String, user: NexusUserEntity, data:
JsonNode) {
val bankConn = NexusBankConnectionEntity.new {
this.connectionId = connId
diff --git a/nexus/src/test/kotlin/DBTest.kt b/nexus/src/test/kotlin/DBTest.kt
index df187ff9..3b818942 100644
--- a/nexus/src/test/kotlin/DBTest.kt
+++ b/nexus/src/test/kotlin/DBTest.kt
@@ -4,33 +4,9 @@ import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.junit.Test
+import withTestDatabase
import java.io.File
-/**
- * Run a block after connecting to the test database.
- * Cleans up the DB file afterwards.
- */
-fun withTestDatabase(f: () -> Unit) {
- val dbfile = "jdbc:sqlite:/tmp/nexus-test.sqlite3"
- File(dbfile).also {
- if (it.exists()) {
- it.delete()
- }
- }
- Database.connect("jdbc:sqlite:$dbfile")
- dbDropTables(dbfile)
- try {
- f()
- }
- finally {
- File(dbfile).also {
- if (it.exists()) {
- it.delete()
- }
- }
- }
-}
-
object MyTable : Table() {
val col1 = text("col1")
val col2 = text("col2")
diff --git a/nexus/src/test/kotlin/MakeEnv.kt b/nexus/src/test/kotlin/MakeEnv.kt
new file mode 100644
index 00000000..5161650e
--- /dev/null
+++ b/nexus/src/test/kotlin/MakeEnv.kt
@@ -0,0 +1,171 @@
+import org.jetbrains.exposed.sql.Database
+import org.jetbrains.exposed.sql.statements.api.ExposedBlob
+import org.jetbrains.exposed.sql.transactions.transaction
+import tech.libeufin.nexus.*
+import tech.libeufin.nexus.dbCreateTables
+import tech.libeufin.nexus.dbDropTables
+import tech.libeufin.sandbox.*
+import tech.libeufin.util.CryptoUtil
+import tech.libeufin.util.EbicsInitState
+import java.io.File
+import tech.libeufin.util.getIban
+
+data class EbicsKeys(
+ val auth: CryptoUtil.RsaCrtKeyPair,
+ val enc: CryptoUtil.RsaCrtKeyPair,
+ val sig: CryptoUtil.RsaCrtKeyPair
+)
+const val TEST_DB_FILE = "/tmp/nexus-test.sqlite3"
+const val TEST_DB_CONN = "jdbc:sqlite:$TEST_DB_FILE"
+val BANK_IBAN = getIban()
+val USER_IBAN = getIban()
+
+val bankKeys = EbicsKeys(
+ auth = CryptoUtil.generateRsaKeyPair(2048),
+ enc = CryptoUtil.generateRsaKeyPair(2048),
+ sig = CryptoUtil.generateRsaKeyPair(2048)
+)
+val userKeys = EbicsKeys(
+ auth = CryptoUtil.generateRsaKeyPair(2048),
+ enc = CryptoUtil.generateRsaKeyPair(2048),
+ sig = CryptoUtil.generateRsaKeyPair(2048)
+)
+/**
+ * Run a block after connecting to the test database.
+ * Cleans up the DB file afterwards.
+ */
+fun withTestDatabase(f: () -> Unit) {
+ val dbfile = TEST_DB_CONN
+ File(dbfile).also {
+ if (it.exists()) {
+ it.delete()
+ }
+ }
+ Database.connect("jdbc:sqlite:$dbfile")
+ dbDropTables(dbfile)
+ tech.libeufin.sandbox.dbDropTables(TEST_DB_CONN)
+ try {
+ f()
+ }
+ finally {
+ File(dbfile).also {
+ if (it.exists()) {
+ it.delete()
+ }
+ }
+ }
+}
+
+fun prepNexusDb() {
+ dbCreateTables(TEST_DB_CONN)
+ transaction {
+ val u = NexusUserEntity.new {
+ username = "foo"
+ passwordHash = "foo"
+ superuser = false
+ }
+ val c = NexusBankConnectionEntity.new {
+ connectionId = "foo"
+ owner = u
+ type = "ebics"
+ }
+ tech.libeufin.nexus.EbicsSubscriberEntity.new {
+ ebicsURL = "http://localhost:5000/ebicsweb"
+ hostID = "eufinSandbox"
+ partnerID = "foo"
+ userID = "foo"
+ systemID = "foo"
+ signaturePrivateKey = ExposedBlob(userKeys.sig.private.encoded)
+ encryptionPrivateKey = ExposedBlob(userKeys.enc.private.encoded)
+ authenticationPrivateKey =
ExposedBlob(userKeys.auth.private.encoded)
+ nexusBankConnection = c
+ ebicsIniState = EbicsInitState.NOT_SENT
+ ebicsHiaState = EbicsInitState.NOT_SENT
+ bankEncryptionPublicKey = ExposedBlob(bankKeys.enc.public.encoded)
+ bankAuthenticationPublicKey =
ExposedBlob(bankKeys.auth.public.encoded)
+ }
+ val a = NexusBankAccountEntity.new {
+ bankAccountName = "mock-bank-account"
+ iban = USER_IBAN
+ bankCode = "SANDBOXX"
+ defaultBankConnection = c
+ highestSeenBankMessageSerialId = 0
+ accountHolder = "foo"
+ }
+ }
+}
+
+fun prepSandboxDb() {
+ tech.libeufin.sandbox.dbCreateTables(TEST_DB_CONN)
+ transaction {
+ val demoBank = DemobankConfigEntity.new {
+ currency = "TESTKUDOS"
+ bankDebtLimit = 10000
+ usersDebtLimit = 1000
+ allowRegistrations = true
+ name = "default"
+ this.withSignupBonus = false
+ captchaUrl = "http://example.com/" // unused
+ }
+ BankAccountEntity.new {
+ iban = BANK_IBAN
+ label = "bank" // used by the wire helper
+ owner = "bank" // used by the person name finder
+ // For now, the model assumes always one demobank
+ this.demoBank = demoBank
+ }
+ EbicsHostEntity.new {
+ this.ebicsVersion = "3.0"
+ this.hostId = "eufinSandbox"
+ this.authenticationPrivateKey =
ExposedBlob(bankKeys.auth.private.encoded)
+ this.encryptionPrivateKey =
ExposedBlob(bankKeys.enc.private.encoded)
+ this.signaturePrivateKey =
ExposedBlob(bankKeys.sig.private.encoded)
+ }
+ val bankAccount = BankAccountEntity.new {
+ iban = USER_IBAN
+ /**
+ * For now, keep same semantics of Pybank: a username
+ * is AS WELL a bank account label. In other words, it
+ * identifies a customer AND a bank account.
+ */
+ label = "foo"
+ owner = "foo"
+ this.demoBank = demoBank
+ isPublic = false
+ }
+ tech.libeufin.sandbox.EbicsSubscriberEntity.new {
+ hostId = "eufinSandbox"
+ partnerId = "foo"
+ userId = "foo"
+ systemId = "foo"
+ signatureKey = EbicsSubscriberPublicKeyEntity.new {
+ rsaPublicKey = ExposedBlob(userKeys.sig.public.encoded)
+ state = KeyState.RELEASED
+ }
+ encryptionKey = EbicsSubscriberPublicKeyEntity.new {
+ rsaPublicKey = ExposedBlob(userKeys.enc.public.encoded)
+ state = KeyState.RELEASED
+ }
+ authenticationKey = EbicsSubscriberPublicKeyEntity.new {
+ rsaPublicKey = ExposedBlob(userKeys.auth.public.encoded)
+ state = KeyState.RELEASED
+ }
+ state = SubscriberState.INITIALIZED
+ nextOrderID = 1
+ this.bankAccount = bankAccount
+ }
+ DemobankCustomerEntity.new {
+ username = "foo"
+ passwordHash = "foo"
+ name = "Foo"
+ }
+ }
+}
+
+fun withNexusAndSandboxUser(f: () -> Unit) {
+ withTestDatabase {
+ prepNexusDb()
+ prepSandboxDb()
+ f()
+ }
+}
\ No newline at end of file
diff --git a/nexus/src/test/kotlin/SchedulingTest.kt
b/nexus/src/test/kotlin/SchedulingTest.kt
new file mode 100644
index 00000000..570d5d4e
--- /dev/null
+++ b/nexus/src/test/kotlin/SchedulingTest.kt
@@ -0,0 +1,140 @@
+import io.ktor.application.*
+import io.ktor.features.*
+import io.ktor.http.*
+import io.ktor.request.*
+import io.ktor.response.*
+import io.ktor.routing.*
+import io.ktor.server.testing.*
+import kotlinx.coroutines.runBlocking
+import org.junit.Ignore
+import org.junit.Test
+import org.w3c.dom.Document
+import tech.libeufin.nexus.*
+import tech.libeufin.sandbox.*
+import tech.libeufin.util.*
+import tech.libeufin.util.ebics_h004.EbicsRequest
+import tech.libeufin.util.ebics_h004.EbicsResponse
+import tech.libeufin.util.ebics_h004.EbicsTypes
+
+
+/**
+ * Data to make the test server return for EBICS
+ * phases. Currently only init is supported.
+ */
+data class EbicsResponses(
+ val init: String,
+ val download: String? = null,
+ val receipt: String? = null
+)
+
+/**
+ * Minimal server responding always the 'init' field of a EbicsResponses
+ * object along a download EBICS message. Suitable to set arbitrary data
+ * in said response. Signs the response assuming the client is the one
+ * created a MakeEnv.kt.
+ */
+fun getCustomEbicsServer(r: EbicsResponses, endpoint: String = "/ebicsweb"):
Application.() -> Unit {
+ val ret: Application.() -> Unit = {
+ install(ContentNegotiation) {
+ register(ContentType.Text.Xml, XMLEbicsConverter())
+ register(ContentType.Text.Plain, XMLEbicsConverter())
+ }
+ routing {
+ post(endpoint) {
+ val requestDocument = this.call.receive<Document>()
+ val req = requestDocument.toObject<EbicsRequest>()
+ val clientKey =
CryptoUtil.loadRsaPublicKey(userKeys.enc.public.encoded)
+ val msgId = EbicsOrderUtil.generateTransactionId()
+ val resp: EbicsResponse = if (
+ req.header.mutable.transactionPhase ==
EbicsTypes.TransactionPhaseType.INITIALISATION
+ ) {
+ val payload = prepareEbicsPayload(r.init, clientKey)
+ EbicsResponse.createForDownloadInitializationPhase(
+ msgId,
+ 1,
+ 4096,
+ payload.second, // for key material
+ payload.first // actual payload
+ )
+ } else {
+ // msgId doesn't have to match the one used for the init
phase.
+ EbicsResponse.createForDownloadReceiptPhase(msgId, true)
+ }
+ val sigEbics = XMLUtil.signEbicsResponse(
+ resp,
+ CryptoUtil.loadRsaPrivateKey(bankKeys.auth.private.encoded)
+ )
+ call.respond(sigEbics)
+ }
+ }
+ }
+ return ret
+}
+
+/**
+ * Remove @Ignore, after having put asserts along tests.
+ */
+@Ignore
+class SchedulingTest {
+ /**
+ * Instruct the server to return invalid CAMT content.
+ */
+ @Test
+ fun inject() {
+ withNexusAndSandboxUser {
+ val payload = """
+ Invalid Camt Document
+ """.trimIndent()
+ withTestApplication(
+ getCustomEbicsServer(EbicsResponses(payload))
+ ) {
+ runBlocking {
+ runTask(
+ client,
+ TaskSchedule(
+ 0L,
+ "test-schedule",
+ "fetch",
+ "bank-account",
+ "mock-bank-account",
+ params =
"{\"level\":\"report\",\"rangeType\":\"all\"}"
+ )
+ )
+ }
+ }
+ }
+ }
+ /**
+ * Create two payments and asks for C52.
+ */
+ @Test
+ fun ordinary() {
+ withNexusAndSandboxUser { // DB prep
+ for (t in 1 .. 2) {
+ wireTransfer(
+ "bank",
+ "foo",
+ "default",
+ "1HJX78AH7WAGBDJTCXJ4JKX022DBCHERA051KH7D3EC48X09G4RG",
+ "TESTKUDOS:5",
+ "xxx"
+ )
+ }
+ withTestApplication(sandboxApp) {
+ runBlocking {
+ runTask(
+ client,
+ TaskSchedule(
+ 0L,
+ "test-schedule",
+ "fetch",
+ "bank-account",
+ "mock-bank-account",
+ params =
"{\"level\":\"report\",\"rangeType\":\"all\"}"
+ )
+ )
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/nexus/src/test/kotlin/SelfContainedDBTest.kt
b/nexus/src/test/kotlin/SelfContainedDBTest.kt
index 5d7974f9..f0322fbc 100644
--- a/nexus/src/test/kotlin/SelfContainedDBTest.kt
+++ b/nexus/src/test/kotlin/SelfContainedDBTest.kt
@@ -13,30 +13,6 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.junit.Test
import java.io.File
-/**
- * Run a block after connecting to the test database.
- * Cleans up the DB file afterwards.
- */
-fun withTestDatabase(f: () -> Unit) {
- val dbfile = "test-db.sqlite3"
- File(dbfile).also {
- if (it.exists()) {
- it.delete()
- }
- }
- Database.connect("jdbc:sqlite:$dbfile", "org.sqlite.JDBC")
- try {
- f()
- }
- finally {
- File(dbfile).also {
- if (it.exists()) {
- it.delete()
- }
- }
- }
-}
-
object ContainedTableWithIntId : IntIdTable() {
val column = text("column")
}
diff --git a/nexus/src/main/resources/logback.xml
b/nexus/src/test/resources/logback-test.xml
similarity index 80%
copy from nexus/src/main/resources/logback.xml
copy to nexus/src/test/resources/logback-test.xml
index b18b437e..cbd96f5f 100644
--- a/nexus/src/main/resources/logback.xml
+++ b/nexus/src/test/resources/logback-test.xml
@@ -11,10 +11,15 @@
<appender-ref ref="STDERR" />
</logger>
+ <logger name="tech.libeufin.sandbox" level="ALL" additivity="false">
+ <appender-ref ref="STDERR" />
+ </logger>
+
<logger name="io.netty" level="WARN"/>
<logger name="ktor" level="WARN"/>
<logger name="Exposed" level="WARN"/>
<logger name="tech.libeufin.util" level="DEBUG"/>
+ <logger name="ch.qos" level="WARN"/>
<root level="WARN">
<appender-ref ref="STDERR"/>
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index fd3524ad..fcbdc3c0 100644
--- 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/Helpers.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 8f0a2944..e96f14b9 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -30,6 +30,9 @@ import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import tech.libeufin.util.*
import java.math.BigDecimal
+import java.security.interfaces.RSAPublicKey
+import java.util.*
+import java.util.zip.DeflaterInputStream
/**
* Helps to communicate Camt values without having
@@ -180,7 +183,8 @@ fun wireTransfer(
creditAccount: String,
demobank: String,
subject: String,
- amount: String // $currency:x.y
+ amount: String, // $currency:x.y
+ pmtInfId: String? = null
): String {
val args: Triple<BankAccountEntity, BankAccountEntity,
DemobankConfigEntity> = transaction {
val debitAccountDb = BankAccountEntity.find {
@@ -215,7 +219,8 @@ fun wireTransfer(
creditAccount = args.second,
demobank = args.third,
subject = subject,
- amount = amountObj.amount.toPlainString()
+ amount = amountObj.amount.toPlainString(),
+ pmtInfId
)
}
/**
@@ -234,6 +239,7 @@ fun wireTransfer(
demobank: DemobankConfigEntity,
subject: String,
amount: String,
+ pmtInfId: String? = null
): String {
// sanity check on the amount, no currency allowed here.
val checkAmount = parseDecimal(amount)
@@ -256,6 +262,7 @@ fun wireTransfer(
account = creditAccount
direction = "CRDT"
this.demobank = demobank
+ this.pmtInfId = pmtInfId
}
BankAccountTransactionEntity.new {
creditorIban = creditAccount.iban
@@ -272,6 +279,7 @@ fun wireTransfer(
account = debitAccount
direction = "DBIT"
this.demobank = demobank
+ this.pmtInfId = pmtInfId
}
}
return transactionRef
@@ -401,4 +409,21 @@ fun getBankAccountWithAuth(call: ApplicationCall):
BankAccountEntity {
"Customer '$username' cannot access bank account '$accountAccessed'"
)
return bankAccount
+}
+
+/**
+ * Compress, encrypt, encode a EBICS payload. The payload
+ * is assumed to be a Zip archive with only one entry.
+ * Return the customer key (second element) along the data.
+ */
+fun prepareEbicsPayload(
+ payload: String, pub: RSAPublicKey
+): Pair<String, CryptoUtil.EncryptionResult> {
+ val zipSingleton = mutableListOf(payload.toByteArray()).zip()
+ val compressedResponse =
DeflaterInputStream(zipSingleton.inputStream()).use {
+ it.readAllBytes()
+ }
+ val enc = CryptoUtil.encryptEbicsE002(compressedResponse, pub)
+ return Pair(Base64.getEncoder().encodeToString(enc.encryptedData), enc)
+
}
\ No newline at end of file
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 7e328f67..fcc4dfc6 100644
--- 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.")
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libeufin] branch master updated (1f70330a -> 39ece551),
gnunet <=
- [libeufin] 03/06: Nexus tests., gnunet, 2022/11/23
- [libeufin] 04/06: comment, gnunet, 2022/11/23
- [libeufin] 01/06: debug, gnunet, 2022/11/23
- [libeufin] 05/06: moving code, gnunet, 2022/11/23
- [libeufin] 02/06: remove newline, gnunet, 2022/11/23
- [libeufin] 06/06: EBICS payload prepare helper., gnunet, 2022/11/23