gnunet-svn
[Top][All Lists]
Advanced

[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 
&quot;SchedulingTest&quot;" />
       <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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]