libeufin

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

commit 4f5778e01dd7f56b4e22408cd4543b342d9d4a70
parent 9cd5454dfc0cbb6f398f71ce8791f405a887c4a1
Author: Marcello Stanisci <ms@taler.net>
Date:   Thu, 30 Apr 2020 14:53:29 +0200

Sandbox admin.

Offering API to tie a bank account to a specific
EBICS subscriber.

Diffstat:
Mintegration-tests/test-ebics.py | 35++++++++++++++++++++++++++++++-----
Msandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt | 20+++++++++++++++++++-
Asandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt | 18++++++++++++++++++
Msandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt | 13+++++++++----
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 24+++++++++++++++++++++++-
5 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/integration-tests/test-ebics.py b/integration-tests/test-ebics.py @@ -5,12 +5,14 @@ from requests import post, get # Steps implemented in this test. # # 1 Prepare the Sandbox to run the test. -# -> Make a EBICS host, and make a EBICS subscriber -# for the test runner. +# -> (a) Make a EBICS host, (b) make a EBICS subscriber +# for the test runner, and (c) assign a IBAN to such +# subscriber. # # 2 Prepare the Nexus to run the test. -# -> Make a Nexus user, and make a EBICS transport -# entity associated with that user. +# -> (a) Make a Nexus user, (b) make a EBICS subscriber +# associated to that user, and (c) fetch the bank +# account owned by that subscriber at the bank. # # 3 Upload keys from Nexus to the Bank (INI & HIA) # 4 Download key from the Bank (HPB) to the Nexus @@ -32,7 +34,12 @@ PARTNER_ID="PARTNER1" USER_ID="USER1" EBICS_VERSION = "H004" -#0 Prepare Sandbox (make Ebics host & one subscriber) +# Subscriber's bank account +SUBSCRIBER_IBAN="GB33BUKB20201555555555" +SUBSCRIBER_BIC="BUKBGB22" +SUBSCRIBER_NAME="Oliver Smith" + +#0.a resp = post( "http://localhost:5000/admin/ebics-host", json=dict( @@ -43,6 +50,7 @@ resp = post( assert(resp.status_code == 200) +#0.b resp = post( "http://localhost:5000/admin/ebics-subscriber", json=dict( @@ -54,6 +62,23 @@ resp = post( assert(resp.status_code == 200) +#0.c, WIP +resp = post( + "http://localhost:5000/admin/ebics-subscriber/bank-account", + json=dict( + subscriber=dict( + hostID=HOST_ID, + partnerID=PARTNER_ID, + userID=USER_ID + ), + iban=SUBSCRIBER_IBAN, + bic=SUBSCRIBER_BIC, + name=SUBSCRIBER_NAME + ) +) + +assert(resp.status_code == 200) + #1 Create a Nexus user resp = post( diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt @@ -225,7 +225,7 @@ class EbicsUploadTransactionChunkEntity(id: EntityID<String>) : Entity<String>(i } /** - * Table that keeps all the payments initiated by pain. + * Table that keeps all the payments initiated by PAIN.001. */ object PaymentsTable : IntIdTable() { val creditorIban = text("creditorIban") @@ -245,6 +245,24 @@ class PaymentEntity(id: EntityID<Int>) : IntEntity(id) { var ebicsSubscriber by EbicsSubscriberEntity referencedOn PaymentsTable.ebicsSubscriber } +/** + * Table that keeps information about which bank accounts (iban+bic+name) + * are active in the system. + */ +object BankAccountsTable : IntIdTable() { + val iban = text("iban") + val bic = text("bic") + val name = text("name") + val subscriber = reference("subscriber", EbicsSubscribersTable) +} +class BankAccountEntity(id: EntityID<Int>) : IntEntity(id) { + companion object : IntEntityClass<BankAccountEntity>(BankAccountsTable) + var iban by BankAccountsTable.iban + var bic by BankAccountsTable.bic + var name by BankAccountsTable.name + var subscriber by EbicsSubscriberEntity referencedOn BankAccountsTable.subscriber +} + fun dbCreateTables() { Database.connect("jdbc:sqlite:libeufin-sandbox.sqlite3", "org.sqlite.JDBC") TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt @@ -0,0 +1,17 @@ +package tech.libeufin.sandbox + +import io.ktor.http.HttpStatusCode +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.transactions.transaction + +fun getEbicsSubscriberFromDetails(userID: String, partnerID: String, hostID: String): EbicsSubscriberEntity { + return transaction { + EbicsSubscriberEntity.find { + (EbicsSubscribersTable.userId eq userID) and (EbicsSubscribersTable.partnerId eq partnerID) and + (EbicsSubscribersTable.hostId eq hostID) + }.firstOrNull() ?: throw SandboxError( + HttpStatusCode.NotFound, + "Ebics subscriber not found" + ) + } +} +\ No newline at end of file diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt @@ -19,10 +19,8 @@ package tech.libeufin.sandbox -/** Error message */ -data class SandboxError( - val message: String -) +import io.ktor.http.HttpStatusCode +import java.lang.Exception /** * Used to show the list of Ebics hosts that exist @@ -59,3 +57,10 @@ data class EbicsSubscriberElement( data class AdminGetSubscribers( var subscribers: MutableList<EbicsSubscriberElement> = mutableListOf() ) + +data class BankAccountRequest( + val subscriber: EbicsSubscriberElement, + val iban: String, + val bic: String, + val name: String +) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -61,6 +61,8 @@ class UnacceptableFractional(badNumber: BigDecimal) : Exception( ) val LOGGER: Logger = LoggerFactory.getLogger("tech.libeufin.sandbox") +data class SandboxError(val statusCode: HttpStatusCode, val reason: String) : java.lang.Exception() + fun findEbicsSubscriber(partnerID: String, userID: String, systemID: String?): EbicsSubscriberEntity? { return if (systemID == null) { EbicsSubscriberEntity.find { @@ -142,6 +144,26 @@ fun main() { } /** EBICS ADMIN ENDPOINTS */ + post("/admin/ebics-subscriber/bank-account") { + val body = call.receive<BankAccountRequest>() + transaction { + val subscriber = getEbicsSubscriberFromDetails( + body.subscriber.userID, + body.subscriber.partnerID, + body.subscriber.hostID + ) + BankAccountEntity.new { + this.subscriber = subscriber + iban = body.iban + bic = body.bic + name = body.name + } + } + call.respondText( + "Bank account created, and associated to the subscriber" + ) + return@post + } post("/admin/ebics-subscriber") { val body = call.receive<EbicsSubscriberElement>() @@ -189,7 +211,7 @@ fun main() { } if (resp == null) call.respond( HttpStatusCode.NotFound, - SandboxError("host not found") + SandboxError(HttpStatusCode.NotFound,"host not found") ) else call.respond(resp) }