gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated: implement generic /connect


From: gnunet
Subject: [libeufin] branch master updated: implement generic /connect
Date: Sun, 24 May 2020 17:30:13 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new 4377295  implement generic /connect
4377295 is described below

commit 437729559aac3ccda0082e8f623454f26a554537
Author: Florian Dold <address@hidden>
AuthorDate: Sun May 24 20:59:48 2020 +0530

    implement generic /connect
---
 integration-tests/test-ebics-highlevel.py          | 288 +++++++++++++++++++++
 nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt    |   5 +
 .../main/kotlin/tech/libeufin/nexus/EbicsClient.kt |   6 +-
 .../src/main/kotlin/tech/libeufin/nexus/Helpers.kt |   5 +-
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  |  78 +++++-
 util/src/main/kotlin/Ebics.kt                      |  35 ++-
 util/src/main/kotlin/ParametersChecks.kt           |   8 +-
 util/src/main/kotlin/XMLUtil.kt                    |   5 +-
 util/src/main/kotlin/strings.kt                    |   2 +-
 9 files changed, 397 insertions(+), 35 deletions(-)

diff --git a/integration-tests/test-ebics-highlevel.py 
b/integration-tests/test-ebics-highlevel.py
new file mode 100755
index 0000000..2732f77
--- /dev/null
+++ b/integration-tests/test-ebics-highlevel.py
@@ -0,0 +1,288 @@
+#!/usr/bin/env python3
+
+from requests import post, get
+from subprocess import call, Popen, PIPE
+from time import sleep
+import os
+import socket
+import hashlib
+import base64
+
+# Steps implemented in this test.
+#
+# 0 Prepare sandbox.
+#  -> (a) Make a EBICS host, (b) make a EBICS subscriber
+#     for the test runner, and (c) assign a IBAN to such
+#     subscriber.
+#
+# 1 Prepare nexus.
+#  -> (a) Make a Nexus user, (b) make a EBICS subscriber
+#     associated to that user
+#
+# 2 Prepare the Ebics bank connection for the nexus user.
+#  -> (a) Upload keys from Nexus to the Bank (INI & HIA),
+#     (b) Download key from the Bank (HPB) to the Nexus,
+#     and (c) Fetch the bank account owned by that subscriber
+#     at the bank.
+
+# 3 Request history from the Nexus to the Bank (C53).
+# 4 Verify that history is empty.
+# 5 Issue a payment from Nexus
+#  -> (a) Prepare & (b) trigger CCT.
+# 6 Request history after submitting the payment,
+#   from Nexus to Bank.
+# 7 Verify that previous payment shows up.
+
+# Nexus user details
+USERNAME = "person"
+PASSWORD = "y"
+USER_AUTHORIZATION_HEADER = "basic {}".format(
+    base64.b64encode(b"person:y").decode("utf-8")
+)
+
+# Admin authentication
+ADMIN_AUTHORIZATION_HEADER = "basic {}".format(
+    base64.b64encode(b"admin:x").decode("utf-8")
+)
+
+# EBICS details
+EBICS_URL = "http://localhost:5000/ebicsweb";
+HOST_ID = "HOST01"
+PARTNER_ID = "PARTNER1"
+USER_ID = "USER1"
+EBICS_VERSION = "H004"
+
+# Subscriber's bank account
+SUBSCRIBER_IBAN = "GB33BUKB20201555555555"
+SUBSCRIBER_BIC = "BUKBGB22"
+SUBSCRIBER_NAME = "Oliver Smith"
+BANK_ACCOUNT_LABEL = "savings"
+
+
+def fail(msg):
+    print(msg)
+    nexus.terminate()
+    sandbox.terminate()
+    exit(1)
+
+
+def checkPorts(ports):
+    for i in ports:
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        try:
+            s.bind(("0.0.0.0", i))
+            s.close()
+        except:
+            print("Port {} is not available".format(i))
+            exit(77)
+
+
+def assertResponse(response):
+    if response.status_code != 200:
+        print("Test failed on URL: {}".format(response.url))
+        # stdout/stderr from both services is A LOT of text.
+        # Confusing to dump all that to console.
+        print("Check nexus.log and sandbox.log, probably under /tmp")
+        nexus.terminate()
+        sandbox.terminate()
+        exit(1)
+    # Allows for finer grained checks.
+    return response
+
+
+# -1 Clean databases and start services.
+os.chdir("..")
+assert 0 == call(["rm", "-f", "sandbox/libeufin-sandbox.sqlite3"])
+assert 0 == call(["rm", "-f", "nexus/libeufin-nexus.sqlite3"])
+DEVNULL = open(os.devnull, "w")
+
+assert 0 == call(
+    ["./gradlew", "nexus:run", "--console=plain", "--args=superuser admin 
--password x"]
+)
+
+# Start nexus
+checkPorts([5001])
+nexus = Popen(
+    ["./gradlew", "nexus:run", "--console=plain", "--args=serve"],
+    stdout=PIPE,
+    stderr=PIPE,
+)
+for i in range(10):
+    try:
+        get("http://localhost:5001/";)
+    except:
+        if i == 9:
+            nexus.terminate()
+            stdout, stderr = nexus.communicate()
+            print("Nexus timed out")
+            print("{}\n{}".format(stdout.decode(), stderr.decode()))
+            exit(77)
+        sleep(2)
+        continue
+    break
+# Start sandbox
+checkPorts([5000])
+sandbox = Popen(["./gradlew", "sandbox:run"], stdout=PIPE, stderr=PIPE)
+for i in range(10):
+    try:
+        get("http://localhost:5000/";)
+    except:
+        if i == 9:
+            nexus.terminate()
+            sandbox.terminate()
+            stdout, stderr = nexus.communicate()
+            print("Sandbox timed out")
+            print("{}\n{}".format(stdout.decode(), stderr.decode()))
+            exit(77)
+        sleep(2)
+        continue
+    break
+
+# 0.a
+assertResponse(
+    post(
+        "http://localhost:5000/admin/ebics/host";,
+        json=dict(hostID=HOST_ID, ebicsVersion=EBICS_VERSION),
+    )
+)
+
+# 0.b
+assertResponse(
+    post(
+        "http://localhost:5000/admin/ebics/subscribers";,
+        json=dict(hostID=HOST_ID, partnerID=PARTNER_ID, userID=USER_ID),
+    )
+)
+
+# 0.c
+assertResponse(
+    post(
+        "http://localhost:5000/admin/ebics/bank-accounts";,
+        json=dict(
+            subscriber=dict(hostID=HOST_ID, partnerID=PARTNER_ID, 
userID=USER_ID),
+            iban=SUBSCRIBER_IBAN,
+            bic=SUBSCRIBER_BIC,
+            name=SUBSCRIBER_NAME,
+            label=BANK_ACCOUNT_LABEL,
+        ),
+    )
+)
+
+# 1.a, make a new nexus user.
+
+assertResponse(
+    post(
+        "http://localhost:5001/users";,
+        headers=dict(Authorization=ADMIN_AUTHORIZATION_HEADER),
+        json=dict(username=USERNAME, password=PASSWORD),
+    )
+)
+
+print("creating bank connection")
+
+# 1.b, make a ebics bank connection for the new user.
+assertResponse(
+    post(
+        "http://localhost:5001/bank-connections";,
+        json=dict(
+            name="my-ebics",
+            source="new",
+            type="ebics",
+            data=dict(
+                ebicsURL=EBICS_URL, hostID=HOST_ID, partnerID=PARTNER_ID, 
userID=USER_ID
+            ),
+        ),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+print("connecting")
+
+assertResponse(
+    post(
+        "http://localhost:5001/bank-connections/my-ebics/connect";,
+        json=dict(),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+
+# 2.c, fetch bank account information
+assertResponse(
+    post(
+        
"http://localhost:5001/bank-connections/my-ebics/ebics/import-accounts";,
+        json=dict(),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+# 3, ask nexus to download history
+assertResponse(
+    post(
+        
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/fetch-transactions";,
+        json=dict(),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+# 4, make sure history is empty
+resp = assertResponse(
+    get(
+        
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/transactions";,
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+if len(resp.json().get("transactions")) != 0:
+    fail("unexpected number of transactions")
+
+# 5.a, prepare a payment
+resp = assertResponse(
+    post(
+        "http://localhost:5001/bank-accounts/{}/prepared-payments".format(
+            BANK_ACCOUNT_LABEL
+        ),
+        json=dict(
+            iban="FR7630006000011234567890189",
+            bic="AGRIFRPP",
+            name="Jacques La Fayette",
+            subject="integration test",
+            amount="EUR:1",
+        ),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+PREPARED_PAYMENT_UUID = resp.json().get("uuid")
+if PREPARED_PAYMENT_UUID == None:
+    fail("Payment UUID not received")
+
+# 5.b, submit prepared statement
+assertResponse(
+    post(
+        
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/prepared-payments/{PREPARED_PAYMENT_UUID}/submit";,
+        json=dict(),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+# 6, request history after payment submission
+assertResponse(
+    post(
+        
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/fetch-transactions";,
+        json=dict(),
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+resp = assertResponse(
+    get(
+        
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/transactions";,
+        headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+    )
+)
+
+if len(resp.json().get("transactions")) != 1:
+    fail("Unexpected number of transactions; should be 1")
+
+nexus.terminate()
+sandbox.terminate()
+print("Test passed!")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index e0d026a..950f186 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -8,6 +8,7 @@ import org.jetbrains.exposed.sql.StdOutSqlLogger
 import org.jetbrains.exposed.sql.addLogger
 import org.jetbrains.exposed.sql.transactions.TransactionManager
 import org.jetbrains.exposed.sql.transactions.transaction
+import tech.libeufin.util.EbicsInitState
 import tech.libeufin.util.amount
 import java.sql.Connection
 
@@ -202,6 +203,8 @@ object EbicsSubscribersTable : IntIdTable() {
     val bankEncryptionPublicKey = blob("bankEncryptionPublicKey").nullable()
     val bankAuthenticationPublicKey = 
blob("bankAuthenticationPublicKey").nullable()
     val nexusBankConnection = reference("nexusBankConnection", 
NexusBankConnectionsTable)
+    val ebicsIniState = enumerationByName("ebicsIniState", 16, 
EbicsInitState::class)
+    val ebicsHiaState = enumerationByName("ebicsHiaState", 16, 
EbicsInitState::class)
 }
 
 class EbicsSubscriberEntity(id: EntityID<Int>) : IntEntity(id) {
@@ -218,6 +221,8 @@ class EbicsSubscriberEntity(id: EntityID<Int>) : 
IntEntity(id) {
     var bankEncryptionPublicKey by 
EbicsSubscribersTable.bankEncryptionPublicKey
     var bankAuthenticationPublicKey by 
EbicsSubscribersTable.bankAuthenticationPublicKey
     var nexusBankConnection by NexusBankConnectionEntity referencedOn  
EbicsSubscribersTable.nexusBankConnection
+    var ebicsIniState by EbicsSubscribersTable.ebicsIniState
+    var ebicsHiaState by EbicsSubscribersTable.ebicsHiaState
 }
 
 object NexusUsersTable : IdTable<String>() {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsClient.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsClient.kt
index 2e28737..ea0a058 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsClient.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsClient.kt
@@ -51,7 +51,7 @@ suspend fun doEbicsDownloadTransaction(
 
     // Initialization phase
     val initDownloadRequestStr = 
createEbicsRequestForDownloadInitialization(subscriberDetails, orderType, 
orderParams)
-    val payloadChunks = LinkedList<String>();
+    val payloadChunks = LinkedList<String>()
     val initResponseStr = client.postToBank(subscriberDetails.ebicsUrl, 
initDownloadRequestStr)
 
     val initResponse = parseAndValidateEbicsResponse(subscriberDetails, 
initResponseStr)
@@ -211,8 +211,8 @@ suspend fun doEbicsHpbRequest(
         request
     )
     val parsedResponse = 
parseAndDecryptEbicsKeyManagementResponse(subscriberDetails, respStr)
-    val orderData = parsedResponse.orderData ?: throw NexusError(
-        HttpStatusCode.InternalServerError,
+    val orderData = parsedResponse.orderData ?: throw EbicsProtocolError(
+        HttpStatusCode.BadGateway,
         "Cannot find data in a HPB response"
     )
     return parseEbicsHpbOrder(orderData)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 0c450a3..301943b 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -1,6 +1,5 @@
 package tech.libeufin.nexus
 
-import io.ktor.application.ApplicationCall
 import io.ktor.client.HttpClient
 import io.ktor.http.HttpStatusCode
 import io.ktor.request.ApplicationRequest
@@ -82,7 +81,9 @@ fun getEbicsSubscriberDetailsInternal(subscriber: 
EbicsSubscriberEntity): EbicsC
 
         customerSignPriv = 
CryptoUtil.loadRsaPrivateKey(subscriber.signaturePrivateKey.toByteArray()),
         customerAuthPriv = 
CryptoUtil.loadRsaPrivateKey(subscriber.authenticationPrivateKey.toByteArray()),
-        customerEncPriv = 
CryptoUtil.loadRsaPrivateKey(subscriber.encryptionPrivateKey.toByteArray())
+        customerEncPriv = 
CryptoUtil.loadRsaPrivateKey(subscriber.encryptionPrivateKey.toByteArray()),
+        ebicsIniState = subscriber.ebicsIniState,
+        ebicsHiaState = subscriber.ebicsHiaState
     )
 }
 
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 9916978..d534855 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -173,6 +173,8 @@ fun createEbicsBankConnectionFromBackup(
             encryptionPrivateKey = SerialBlob(encKey.encoded)
             authenticationPrivateKey = SerialBlob(authKey.encoded)
             nexusBankConnection = bankConn
+            ebicsIniState = EbicsInitState.UNKNOWN
+            ebicsHiaState = EbicsInitState.UNKNOWN
         }
     } catch (e: Exception) {
         throw NexusError(
@@ -188,20 +190,22 @@ fun createEbicsBankConnection(bankConnectionName: String, 
user: NexusUserEntity,
         owner = user
         type = "ebics"
     }
-    val data = jacksonObjectMapper().treeToValue(data, 
EbicsNewTransport::class.java)
+    val newTransportData = jacksonObjectMapper().treeToValue(data, 
EbicsNewTransport::class.java)
     val pairA = CryptoUtil.generateRsaKeyPair(2048)
     val pairB = CryptoUtil.generateRsaKeyPair(2048)
     val pairC = CryptoUtil.generateRsaKeyPair(2048)
     EbicsSubscriberEntity.new {
-        ebicsURL = data.ebicsURL
-        hostID = data.hostID
-        partnerID = data.partnerID
-        userID = data.userID
-        systemID = data.systemID
+        ebicsURL = newTransportData.ebicsURL
+        hostID = newTransportData.hostID
+        partnerID = newTransportData.partnerID
+        userID = newTransportData.userID
+        systemID = newTransportData.systemID
         signaturePrivateKey = SerialBlob(pairA.private.encoded)
         encryptionPrivateKey = SerialBlob(pairB.private.encoded)
         authenticationPrivateKey = SerialBlob(pairC.private.encoded)
         nexusBankConnection = bankConn
+        ebicsIniState = EbicsInitState.NOT_SENT
+        ebicsHiaState = EbicsInitState.NOT_SENT
     }
 }
 
@@ -251,7 +255,7 @@ fun serverMain() {
                     cause.statusCode
                 )
             }
-            exception<UtilError> { cause ->
+            exception<EbicsProtocolError> { cause ->
                 logger.error("Exception while handling '${call.request.uri}'", 
cause)
                 call.respondText(
                     cause.reason,
@@ -704,7 +708,65 @@ fun serverMain() {
             }
 
             post("/bank-connections/{connid}/connect") {
-                throw NotImplementedError()
+                val subscriber = transaction {
+                    val user = authenticateRequest(call.request)
+                    val conn = requireBankConnection(call, "connid")
+                    if (conn.type != "ebics") {
+                        throw NexusError(
+                            HttpStatusCode.BadRequest,
+                            "bank connection is not of type 'ebics' (but 
'${conn.type}')"
+                        )
+                    }
+                    getEbicsSubscriberDetails(user.id.value, conn.id.value)
+                }
+                if (subscriber.bankAuthPub != null && subscriber.bankEncPub != 
null) {
+                    call.respond(object {
+                        val ready = true
+                    })
+                    return@post
+                }
+
+                val iniDone = when (subscriber.ebicsIniState) {
+                    EbicsInitState.NOT_SENT, EbicsInitState.UNKNOWN -> {
+                        val iniResp = doEbicsIniRequest(client, subscriber)
+                        iniResp.bankReturnCode == EbicsReturnCode.EBICS_OK && 
iniResp.technicalReturnCode == EbicsReturnCode.EBICS_OK
+                    }
+                    else -> {
+                        false
+                    }
+                }
+                val hiaDone = when (subscriber.ebicsHiaState) {
+                    EbicsInitState.NOT_SENT, EbicsInitState.UNKNOWN -> {
+                        val hiaResp = doEbicsHiaRequest(client, subscriber)
+                        hiaResp.bankReturnCode == EbicsReturnCode.EBICS_OK && 
hiaResp.technicalReturnCode == EbicsReturnCode.EBICS_OK
+                    }
+                    else -> {
+                        false
+                    }
+                }
+
+                val hpbData = try {
+                    doEbicsHpbRequest(client, subscriber)
+                } catch (e: EbicsProtocolError) {
+                    logger.warn("failed hpb request", e)
+                    null
+                }
+                transaction {
+                    val conn = requireBankConnection(call, "connid")
+                    val subscriberEntity =
+                        EbicsSubscriberEntity.find { 
EbicsSubscribersTable.nexusBankConnection eq conn.id }.first()
+                    if (iniDone) {
+                        subscriberEntity.ebicsIniState = EbicsInitState.SENT
+                    }
+                    if (hiaDone) {
+                        subscriberEntity.ebicsHiaState = EbicsInitState.SENT
+                    }
+                    if (hpbData != null) {
+                        subscriberEntity.bankAuthenticationPublicKey = 
SerialBlob(hpbData.authenticationPubKey.encoded)
+                        subscriberEntity.bankEncryptionPublicKey = 
SerialBlob(hpbData.encryptionPubKey.encoded)
+                    }
+                }
+                call.respond(object {})
             }
 
             post("/bank-connections/{connid}/ebics/send-ini") {
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
index 0f62082..feaf4bd 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/util/src/main/kotlin/Ebics.kt
@@ -38,7 +38,8 @@ import java.util.*
 import java.util.zip.DeflaterInputStream
 import javax.xml.datatype.DatatypeFactory
 
-data class UtilError(val statusCode: HttpStatusCode, val reason: String) : 
Exception()
+data class EbicsProtocolError(val statusCode: HttpStatusCode, val reason: 
String) : Exception(reason)
+
 data class EbicsDateRange(val start: LocalDate, val end: LocalDate)
 
 sealed class EbicsOrderParams
@@ -51,6 +52,10 @@ data class EbicsGenericOrderParams(
     val params: Map<String, String> = mapOf()
 ) : EbicsOrderParams()
 
+enum class EbicsInitState {
+    SENT, NOT_SENT, UNKNOWN
+}
+
 /**
  * This class is a mere container that keeps data found
  * in the database and that is further needed to sign / verify
@@ -66,7 +71,9 @@ data class EbicsClientSubscriberDetails(
     val hostId: String,
     val customerEncPriv: RSAPrivateCrtKey,
     val customerAuthPriv: RSAPrivateCrtKey,
-    val customerSignPriv: RSAPrivateCrtKey
+    val customerSignPriv: RSAPrivateCrtKey,
+    val ebicsIniState: EbicsInitState,
+    val ebicsHiaState: EbicsInitState
 )
 
 /**
@@ -237,11 +244,11 @@ fun createEbicsRequestForDownloadInitialization(
         subscriberDetails.hostId,
         getNonce(128),
         
DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar()),
-        subscriberDetails.bankEncPub ?: throw UtilError(
+        subscriberDetails.bankEncPub ?: throw EbicsProtocolError(
             HttpStatusCode.BadRequest,
             "Invalid subscriber state 'bankEncPub' missing, please send HPB 
first"
         ),
-        subscriberDetails.bankAuthPub ?: throw UtilError(
+        subscriberDetails.bankAuthPub ?: throw EbicsProtocolError(
             HttpStatusCode.BadRequest,
             "Invalid subscriber state 'bankAuthPub' missing, please send HPB 
first"
         ),
@@ -312,7 +319,7 @@ enum class EbicsReturnCode(val errorCode: String) {
                     return x
                 }
             }
-            throw UtilError(HttpStatusCode.InternalServerError, "Unknown EBICS 
status code: $errorCode")
+            throw EbicsProtocolError(HttpStatusCode.InternalServerError, 
"Unknown EBICS status code: $errorCode")
         }
     }
 }
@@ -338,14 +345,14 @@ fun parseAndDecryptEbicsKeyManagementResponse(
     val resp = try {
         XMLUtil.convertStringToJaxb<EbicsKeyManagementResponse>(responseStr)
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.InternalServerError, "Invalid XML 
received from bank")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Invalid 
XML received from bank")
     }
     val retCode = EbicsReturnCode.lookup(resp.value.header.mutable.returnCode)
 
     val daeXml = resp.value.body.dataTransfer?.dataEncryptionInfo
     val orderData = if (daeXml != null) {
         val dae = DataEncryptionInfo(daeXml.transactionKey, 
daeXml.encryptionPubKeyDigest.value)
-        val encOrderData = resp.value.body.dataTransfer?.orderData?.value ?: 
throw UtilError(
+        val encOrderData = resp.value.body.dataTransfer?.orderData?.value ?: 
throw EbicsProtocolError(
             HttpStatusCode.InternalServerError, "Invalid XML/orderData 
received from bank"
         )
         decryptAndDecompressResponse(subscriberDetails, dae, 
listOf(encOrderData))
@@ -371,7 +378,7 @@ fun parseEbicsHpbOrder(orderDataRaw: ByteArray): 
HpbResponseData {
     val resp = try {
         
XMLUtil.convertStringToJaxb<HPBResponseOrderData>(orderDataRaw.toString(Charsets.UTF_8))
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.InternalServerError, "Invalid XML (as 
HPB response) received from bank")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Invalid 
XML (as HPB response) received from bank")
     }
     val encPubKey = CryptoUtil.loadRsaPublicKeyFromComponents(
         resp.value.encryptionPubKeyInfo.pubKeyValue.rsaKeyValue.modulus,
@@ -397,23 +404,23 @@ fun parseAndValidateEbicsResponse(
     val responseDocument = try {
         XMLUtil.parseStringIntoDom(responseStr)
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.InternalServerError, "Invalid XML (as 
EbicsResponse) received from bank")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Invalid 
XML (as EbicsResponse) received from bank")
     }
 
     if (!XMLUtil.verifyEbicsDocument(
             responseDocument,
-            subscriberDetails.bankAuthPub ?: throw UtilError(
+            subscriberDetails.bankAuthPub ?: throw EbicsProtocolError(
                 HttpStatusCode.BadRequest,
                 "Invalid subscriber state: bankAuthPub missing, please send 
HPB first"
             )
         )
     ) {
-        throw UtilError(HttpStatusCode.InternalServerError, "Bank's signature 
validation failed")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Bank's 
signature validation failed")
     }
     val resp = try {
         XMLUtil.convertStringToJaxb<EbicsResponse>(responseStr)
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.InternalServerError, "Could not 
transform string-response from bank into JAXB")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Could 
not transform string-response from bank into JAXB")
     }
 
     val bankReturnCodeStr = resp.value.body.returnCode.value
@@ -452,7 +459,7 @@ fun getDecryptionKey(subscriberDetails: 
EbicsClientSubscriberDetails, pubDigest:
     if (pubDigest.contentEquals(encPubDigest)) {
         return subscriberDetails.customerEncPriv
     }
-    throw UtilError(HttpStatusCode.NotFound, "Could not find customer's public 
key")
+    throw EbicsProtocolError(HttpStatusCode.NotFound, "Could not find 
customer's public key")
 }
 
 /**
@@ -512,7 +519,7 @@ fun parseEbicsHEVResponse(respStr: String): EbicsHevDetails 
{
         XMLUtil.convertStringToJaxb<HEVResponse>(respStr)
     } catch (e: Exception) {
         logger.error("Exception while parsing HEV response", e)
-        throw UtilError(HttpStatusCode.InternalServerError, "Invalid HEV 
received from bank")
+        throw EbicsProtocolError(HttpStatusCode.InternalServerError, "Invalid 
HEV received from bank")
     }
     val versions = resp.value.versionNumber.map { versionNumber ->
         EbicsVersionSpec(versionNumber.protocolVersion, versionNumber.value)
diff --git a/util/src/main/kotlin/ParametersChecks.kt 
b/util/src/main/kotlin/ParametersChecks.kt
index abf5bc2..64e4963 100644
--- a/util/src/main/kotlin/ParametersChecks.kt
+++ b/util/src/main/kotlin/ParametersChecks.kt
@@ -7,12 +7,12 @@ fun expectInt(param: String): Int {
     return try {
         param.toInt()
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.BadRequest,"'$param' is not Int")
+        throw EbicsProtocolError(HttpStatusCode.BadRequest,"'$param' is not 
Int")
     }
 }
 
 fun <T>expectNonNull(param: T?): T {
-    return param ?: throw UtilError(
+    return param ?: throw EbicsProtocolError(
         HttpStatusCode.BadRequest,
         "Non-null value expected."
     )
@@ -22,7 +22,7 @@ fun expectLong(param: String): Long {
     return try {
         param.toLong()
     } catch (e: Exception) {
-        throw UtilError(HttpStatusCode.BadRequest,"'$param' is not Long")
+        throw EbicsProtocolError(HttpStatusCode.BadRequest,"'$param' is not 
Long")
     }
 }
 
@@ -36,5 +36,5 @@ fun expectLong(param: String?): Long? {
 
 fun ApplicationCall.expectUrlParameter(name: String): String {
     return this.request.queryParameters[name]
-        ?: throw UtilError(HttpStatusCode.BadRequest, "Parameter '$name' not 
provided in URI")
+        ?: throw EbicsProtocolError(HttpStatusCode.BadRequest, "Parameter 
'$name' not provided in URI")
 }
\ No newline at end of file
diff --git a/util/src/main/kotlin/XMLUtil.kt b/util/src/main/kotlin/XMLUtil.kt
index 7be64b9..ecaeb35 100644
--- a/util/src/main/kotlin/XMLUtil.kt
+++ b/util/src/main/kotlin/XMLUtil.kt
@@ -38,7 +38,6 @@ import java.io.*
 import java.security.PrivateKey
 import java.security.PublicKey
 import java.security.interfaces.RSAPrivateCrtKey
-import javax.print.DocFlavor
 import javax.xml.XMLConstants
 import javax.xml.bind.JAXBContext
 import javax.xml.bind.JAXBElement
@@ -411,7 +410,7 @@ class XMLUtil private constructor() {
         fun getNodeFromXpath(doc: Document, query: String): Node {
             val xpath = XPathFactory.newInstance().newXPath()
             val ret = xpath.evaluate(query, doc, XPathConstants.NODE)
-                ?: throw UtilError(HttpStatusCode.NotFound, "Unsuccessful 
XPath query string: $query")
+                ?: throw EbicsProtocolError(HttpStatusCode.NotFound, 
"Unsuccessful XPath query string: $query")
             return ret as Node
         }
 
@@ -419,7 +418,7 @@ class XMLUtil private constructor() {
             val xpath = XPathFactory.newInstance().newXPath()
             val ret = xpath.evaluate(query, doc, XPathConstants.STRING) as 
String
             if (ret.isEmpty()) {
-                throw UtilError(HttpStatusCode.NotFound, "Unsuccessful XPath 
query string: $query")
+                throw EbicsProtocolError(HttpStatusCode.NotFound, 
"Unsuccessful XPath query string: $query")
             }
             return ret as String
         }
diff --git a/util/src/main/kotlin/strings.kt b/util/src/main/kotlin/strings.kt
index 62e3265..279f996 100644
--- a/util/src/main/kotlin/strings.kt
+++ b/util/src/main/kotlin/strings.kt
@@ -79,7 +79,7 @@ data class AmountWithCurrency(
 
 fun parseAmount(amount: String): AmountWithCurrency {
     val match = Regex("([A-Z]+):([0-9]+(\\.[0-9]+)?)").find(amount) ?: throw
-    UtilError(HttpStatusCode.BadRequest, "invalid amount: $amount")
+    EbicsProtocolError(HttpStatusCode.BadRequest, "invalid amount: $amount")
     val (currency, number) = match.destructured
     return AmountWithCurrency(currency, Amount(number))
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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