summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xintegration-tests/test-ebics-highlevel.py2
-rwxr-xr-xintegration-tests/test-ebics.py10
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt125
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt73
4 files changed, 111 insertions, 99 deletions
diff --git a/integration-tests/test-ebics-highlevel.py b/integration-tests/test-ebics-highlevel.py
index 4961f820..da4306c9 100755
--- a/integration-tests/test-ebics-highlevel.py
+++ b/integration-tests/test-ebics-highlevel.py
@@ -152,7 +152,7 @@ assertResponse(
# 2.c, fetch bank account information
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/import-accounts",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/import-accounts",
json=dict(),
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
diff --git a/integration-tests/test-ebics.py b/integration-tests/test-ebics.py
index c81a1cee..5b5c2563 100755
--- a/integration-tests/test-ebics.py
+++ b/integration-tests/test-ebics.py
@@ -144,7 +144,7 @@ print("sending ini & hia")
# 2.a, upload keys to the bank (INI & HIA)
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/send-ini",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/send-ini",
json=dict(),
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
@@ -152,7 +152,7 @@ assertResponse(
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/send-hia",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/send-hia",
json=dict(),
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
@@ -161,7 +161,7 @@ assertResponse(
# 2.b, download keys from the bank (HPB)
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/send-hpb",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/send-hpb",
json=dict(),
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
@@ -170,7 +170,7 @@ assertResponse(
# Test download transaction (TSD, LibEuFin-specific test order type)
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/download/tsd",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/download/tsd",
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
)
@@ -178,7 +178,7 @@ assertResponse(
# 2.c, fetch bank account information
assertResponse(
post(
- "http://localhost:5001/bank-connections/my-ebics/import-accounts",
+ "http://localhost:5001/bank-connections/my-ebics/ebics/import-accounts",
json=dict(),
headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
)
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 35176631..48546b20 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -325,6 +325,45 @@ private fun getEbicsSubscriberDetails(bankConnectionId: String): EbicsClientSubs
return getEbicsSubscriberDetailsInternal(subscriber)
}
+suspend fun ebicsFetchAccounts(connId: String, client: HttpClient) {
+ val subscriberDetails = transaction {
+ getEbicsSubscriberDetails(connId)
+ }
+ val response = doEbicsDownloadTransaction(
+ client, subscriberDetails, "HTD", EbicsStandardOrderParams()
+ )
+ when (response) {
+ is EbicsDownloadBankErrorResult -> {
+ throw NexusError(
+ HttpStatusCode.BadGateway,
+ response.returnCode.errorCode
+ )
+ }
+ is EbicsDownloadSuccessResult -> {
+ val payload = XMLUtil.convertStringToJaxb<HTDResponseOrderData>(
+ response.orderData.toString(Charsets.UTF_8)
+ )
+ transaction {
+ payload.value.partnerInfo.accountInfoList?.forEach {
+ OfferedBankAccountEntity.new(id = it.id) {
+ accountHolder = it.accountHolder ?: "NOT-GIVEN"
+ iban = it.accountNumberList?.filterIsInstance<EbicsTypes.GeneralAccountNumber>()
+ ?.find { it.international }?.value
+ ?: throw NexusError(HttpStatusCode.NotFound, reason = "bank gave no IBAN")
+ bankCode = it.bankCodeList?.filterIsInstance<EbicsTypes.GeneralBankCode>()
+ ?.find { it.international }?.value
+ ?: throw NexusError(
+ HttpStatusCode.NotFound,
+ reason = "bank gave no BIC"
+ )
+ bankConnection = requireBankConnectionInternal(connId)
+ }
+ }
+ }
+ }
+ }
+}
+
fun Route.ebicsBankProtocolRoutes(client: HttpClient) {
post("test-host") {
val r = call.receiveJson<EbicsHostTestRequest>()
@@ -392,92 +431,6 @@ fun Route.ebicsBankConnectionRoutes(client: HttpClient) {
}
call.respond(object {})
}
- // persists raw / to-be-imported bank accounts
- post("/accounts/fetch") {
- val res = transaction {
- authenticateRequest(call.request)
- val conn = requireBankConnection(call, "connid")
- if (conn.type != "ebics") {
- throw NexusError(HttpStatusCode.BadRequest, "bank connection is not of type 'ebics'")
- }
- object {
- val subscriberDetails = getEbicsSubscriberDetails(conn.id.value)
- val connid = conn.id.value
- }
- }
- val response = doEbicsDownloadTransaction(
- client, res.subscriberDetails, "HTD", EbicsStandardOrderParams()
- )
- when (response) {
- is EbicsDownloadBankErrorResult -> {
- throw NexusError(
- HttpStatusCode.BadGateway,
- response.returnCode.errorCode
- )
- }
- is EbicsDownloadSuccessResult -> {
- val payload = XMLUtil.convertStringToJaxb<HTDResponseOrderData>(
- response.orderData.toString(Charsets.UTF_8)
- )
- transaction {
- val conn = requireBankConnection(call, "connid")
- payload.value.partnerInfo.accountInfoList?.forEach {
- OfferedBankAccountEntity.new(id = it.id) {
- accountHolder = it.accountHolder ?: "NOT-GIVEN"
- iban = it.accountNumberList?.filterIsInstance<EbicsTypes.GeneralAccountNumber>()
- ?.find { it.international }?.value
- ?: throw NexusError(HttpStatusCode.NotFound, reason = "bank gave no IBAN")
- bankCode = it.bankCodeList?.filterIsInstance<EbicsTypes.GeneralBankCode>()
- ?.find { it.international }?.value
- ?: throw NexusError(
- HttpStatusCode.NotFound,
- reason = "bank gave no BIC"
- )
- bankConnection = conn
- }
- }
- }
- }
- }
- call.respond(object {})
- }
-
- // show only non imported accounts.
- get("/accounts") {
- val ret = BankAccounts()
- transaction {
- val conn = requireBankConnection(call, "connid")
- OfferedBankAccountEntity.find {
- OfferedBankAccountsTable.bankConnection eq conn.id.value and not(OfferedBankAccountsTable.imported)
- }.forEach {
- ret.accounts.add(
- BankAccount(
- iban = it.iban, bic = it.bankCode, holder = it.accountHolder, account = it.id.value
- )
- )
- }
- }
- call.respond(ret)
- }
-
- post("/accounts/import") {
- val body = call.receive<ImportBankAccount>()
- transaction {
- val conn = requireBankConnection(call, "connid")
- val account = OfferedBankAccountEntity.findById(body.accountId) ?: throw NexusError(
- HttpStatusCode.NotFound, "Could not found raw bank account '${body.accountId}'"
- )
- NexusBankAccountEntity.new(body.localName) {
- iban = account.iban
- bankCode = account.bankCode
- defaultBankConnection = conn
- highestSeenBankMessageId = 0
- accountHolder = account.accountHolder
- }
- account.imported = true
- }
- call.respond(object {})
- }
/**
* Directly import accounts. Used for testing.
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
index 3186d75e..f0514503 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -49,6 +49,7 @@ import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.toByteReadChannel
import io.ktor.utils.io.jvm.javaio.toInputStream
import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.not
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.event.Level
import tech.libeufin.nexus.*
@@ -58,6 +59,8 @@ import tech.libeufin.nexus.bankaccount.getPaymentInitiation
import tech.libeufin.nexus.bankaccount.submitPaymentInitiation
import tech.libeufin.nexus.ebics.*
import tech.libeufin.util.*
+import tech.libeufin.util.ebics_h004.EbicsTypes
+import tech.libeufin.util.ebics_h004.HTDResponseOrderData
import tech.libeufin.util.logger
import java.lang.IllegalArgumentException
import java.net.URLEncoder
@@ -178,17 +181,20 @@ fun createLoopbackBankConnection(bankConnectionName: String, user: NexusUserEnti
}
}
+fun requireBankConnectionInternal(connId: String): NexusBankConnectionEntity {
+ val conn = transaction { NexusBankConnectionEntity.findById(connId) }
+ if (conn == null) {
+ throw NexusError(HttpStatusCode.NotFound, "bank connection '$connId' not found")
+ }
+ return conn
+}
fun requireBankConnection(call: ApplicationCall, parameterKey: String): NexusBankConnectionEntity {
val name = call.parameters[parameterKey]
if (name == null) {
throw NexusError(HttpStatusCode.InternalServerError, "no parameter for bank connection")
}
- val conn = transaction { NexusBankConnectionEntity.findById(name) }
- if (conn == null) {
- throw NexusError(HttpStatusCode.NotFound, "bank connection '$name' not found")
- }
- return conn
+ return requireBankConnectionInternal(name)
}
@@ -700,7 +706,7 @@ fun serverMain(dbName: String, host: String) {
val pdfBytes = getEbicsKeyLetterPdf(conn)
call.respondBytes(pdfBytes, ContentType("application", "pdf"))
}
- else -> throw NexusError(HttpStatusCode.NotImplemented, "keyletter not supporte dfor ${conn.type}")
+ else -> throw NexusError(HttpStatusCode.NotImplemented, "keyletter not supported for ${conn.type}")
}
}
@@ -766,7 +772,60 @@ fun serverMain(dbName: String, host: String) {
}
route("/bank-connections/{connid}") {
- ebicsBankConnectionRoutes(client)
+ // only ebics specific tasks under this part.
+ route("/ebics") {
+ ebicsBankConnectionRoutes(client)
+ }
+ post("/accounts/fetch") {
+ val conn = transaction {
+ authenticateRequest(call.request)
+ requireBankConnection(call, "connid")
+ }
+ when(conn.type) {
+ "ebics" -> {
+ ebicsFetchAccounts(conn.id.value, client)
+ }
+ else -> throw NexusError(HttpStatusCode.NotImplemented, "connection not supported for ${conn.type}")
+ }
+ call.respond(object {})
+ }
+
+ // show all the offered accounts (both imported and non)
+ get("/accounts") {
+ val ret = BankAccounts()
+ transaction {
+ val conn = requireBankConnection(call, "connid")
+ OfferedBankAccountEntity.find {
+ OfferedBankAccountsTable.bankConnection eq conn.id.value
+ }.forEach {
+ ret.accounts.add(
+ BankAccount(
+ iban = it.iban, bic = it.bankCode, holder = it.accountHolder, account = it.id.value
+ )
+ )
+ }
+ }
+ call.respond(ret)
+ }
+ // import one account into libeufin.
+ post("/accounts/import") {
+ val body = call.receive<ImportBankAccount>()
+ transaction {
+ val conn = requireBankConnection(call, "connid")
+ val account = OfferedBankAccountEntity.findById(body.accountId) ?: throw NexusError(
+ HttpStatusCode.NotFound, "Could not found raw bank account '${body.accountId}'"
+ )
+ NexusBankAccountEntity.new(body.localName) {
+ iban = account.iban
+ bankCode = account.bankCode
+ defaultBankConnection = conn
+ highestSeenBankMessageId = 0
+ accountHolder = account.accountHolder
+ }
+ account.imported = true
+ }
+ call.respond(object {})
+ }
}
route("/facades/{fcid}/taler") {