libeufin

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

commit 66a78ea164ce7816c9f364ebea2378c726d18c5b
parent e5e2ba20a612aaebeb3365f6d07640abb22f8d45
Author: Marcello Stanisci <ms@taler.net>
Date:   Wed, 29 Apr 2020 10:32:27 +0200

Integration tests.

Get until /sendHIA to pass.

Diffstat:
Aintegration-tests/test.py | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 17+++++++++--------
Mnexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt | 13+++++++++----
Mnexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt | 1-
Mnexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 35++++++++++++++++++++---------------
Mnexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 6++----
6 files changed, 94 insertions(+), 32 deletions(-)

diff --git a/integration-tests/test.py b/integration-tests/test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +from requests import post, get + +#1 Create a Nexus user +USERNAME="person" + +resp = post( + "http://localhost:5001/users/{}".format(USERNAME), + json=dict( + password="secret" + ) +) + +assert(resp.status_code == 200) + +#2 Create a EBICS user + +resp = post( + "http://localhost:5001/ebics/subscribers/{}".format(USERNAME), + json=dict( + ebicsURL="http://localhost:5000/ebicsweb", + hostID="HOST1", + partnerID="PARTNER1", + userID="USER1" + ) +) + +assert(resp.status_code == 200) + +#3 Upload keys to the bank INI & HIA +resp = post( + "http://localhost:5001/ebics/subscribers/{}/sendINI".format(USERNAME), + json=dict() +) + +assert(resp.status_code == 200) + +resp = post( + "http://localhost:5001/ebics/subscribers/{}/sendHIA".format(USERNAME), + json=dict() +) + +assert(resp.status_code == 200) + +#4 Download keys from the bank HPB +#5 Request history +#6 Prepare a payment +#7 Execute such payment via EBICS +#8 Request history again +#9 Exit + +# The Nexus should connect to the Sandbox for +# these tests! diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt @@ -212,7 +212,7 @@ object NexusUsersTable : IdTable<String>() { override val id = varchar("id", ID_MAX_LENGTH).entityId().primaryKey() val ebicsSubscriber = reference("ebicsSubscriber", EbicsSubscribersTable).nullable() val testSubscriber = reference("testSubscriber", EbicsSubscribersTable).nullable() - val password = EbicsSubscribersTable.blob("password").nullable() + val password = blob("password").nullable() } class NexusUserEntity(id: EntityID<String>) : Entity<String>(id) { @@ -249,13 +249,14 @@ fun dbCreateTables() { TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE transaction { addLogger(StdOutSqlLogger) - SchemaUtils.create( - Pain001Table, - EbicsSubscribersTable, - BankAccountsTable, - RawBankTransactionsTable, - TalerIncomingPayments, - TalerRequestedPayments + SchemaUtils.create( + Pain001Table, + EbicsSubscribersTable, + BankAccountsTable, + RawBankTransactionsTable, + TalerIncomingPayments, + TalerRequestedPayments, + NexusUsersTable ) } } \ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt @@ -22,7 +22,7 @@ import java.time.ZoneId fun getSubscriberEntityFromNexusUserId(nexusUserId: String?): EbicsSubscriberEntity { return transaction { - val nexusUser = expectNexusIdTransaction(expectId(nexusUserId)) + val nexusUser = extractNexusUser(expectId(nexusUserId)) getEbicsSubscriberFromUser(nexusUser) } } @@ -138,7 +138,7 @@ fun getEbicsSubscriberFromUser(nexusUser: NexusUserEntity): EbicsSubscriberEntit fun getSubscriberDetailsFromNexusUserId(id: String): EbicsClientSubscriberDetails { return transaction { - val nexusUser = expectNexusIdTransaction(id) + val nexusUser = extractNexusUser(id) getSubscriberDetailsInternal(nexusUser.ebicsSubscriber ?: throw NexusError( HttpStatusCode.NotFound, "Cannot get details for non-activated subscriber!" @@ -319,11 +319,16 @@ fun expectId(param: String?): String { } /* Needs a transaction{} block to be called */ -fun expectNexusIdTransaction(param: String?): NexusUserEntity { +fun extractNexusUser(param: String?): NexusUserEntity { if (param == null) { throw NexusError(HttpStatusCode.BadRequest, "Null Id given") } - return NexusUserEntity.findById(param) ?: throw NexusError(HttpStatusCode.NotFound, "Subscriber: $param not found") + return transaction{ + NexusUserEntity.findById(param) ?: throw NexusError( + HttpStatusCode.NotFound, + "Subscriber: $param not found" + ) + } } fun ApplicationCall.expectUrlParameter(name: String): String { diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt @@ -100,7 +100,6 @@ data class NexusUser( /** Instructs the nexus to CREATE a new user */ data class NexusUserRequest( - val userID: String, val password: String? ) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt @@ -179,7 +179,7 @@ fun main() { /** Get all the details associated with a NEXUS user */ get("/user/{id}") { val response = transaction { - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) + val nexusUser = extractNexusUser(call.parameters["id"]) NexusUser( userID = nexusUser.id.value ) @@ -240,7 +240,7 @@ fun main() { val nexusUserId = expectId(call.parameters["id"]) val ret = PaymentsInfo() transaction { - val nexusUser = expectNexusIdTransaction(nexusUserId) + val nexusUser = extractNexusUser(nexusUserId) val bankAccountsMap = UserToBankAccountEntity.find { UserToBankAccountsTable.nexusUser eq nexusUser.id } @@ -268,7 +268,7 @@ fun main() { post("/users/{id}/accounts/{acctid}/prepare-payment") { val acctid = transaction { val accountInfo = expectAcctidTransaction(call.parameters["acctid"]) - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) + val nexusUser = extractNexusUser(call.parameters["id"]) if (!userHasRights(nexusUser, accountInfo)) { throw NexusError( HttpStatusCode.BadRequest, @@ -285,14 +285,13 @@ fun main() { ) return@post } - /** Associate a EBICS subscriber to the existing user */ - post("/ebics/{id}/subscriber") { + post("/ebics/subscribers/{id}") { + val nexusUser = extractNexusUser(call.parameters["id"]) val body = call.receive<EbicsSubscriber>() val pairA = CryptoUtil.generateRsaKeyPair(2048) val pairB = CryptoUtil.generateRsaKeyPair(2048) val pairC = CryptoUtil.generateRsaKeyPair(2048) - transaction { val newEbicsSubscriber = EbicsSubscriberEntity.new { ebicsURL = body.ebicsURL @@ -304,10 +303,14 @@ fun main() { encryptionPrivateKey = SerialBlob(pairB.private.encoded) authenticationPrivateKey = SerialBlob(pairC.private.encoded) } - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) nexusUser.ebicsSubscriber = newEbicsSubscriber } - + call.respondText( + "EBICS user successfully created", + ContentType.Text.Plain, + HttpStatusCode.OK + ) + return@post } post("/ebics/subscribers/{id}/restoreBackup") { val body = call.receive<EbicsKeysBackupJson>() @@ -370,7 +373,7 @@ fun main() { /** EBICS CONVENIENCE */ get("/ebics/subscribers/{id}/pubkeys") { - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) + val nexusUser = extractNexusUser(call.parameters["id"]) val response = transaction { val subscriber = getEbicsSubscriberFromUser(nexusUser) val authPriv = CryptoUtil.loadRsaPrivateKey(subscriber.authenticationPrivateKey.toByteArray()) @@ -415,7 +418,7 @@ fun main() { val timeLine = timeFormat.format(now) var hostID = "" transaction { - val nexusUser = expectNexusIdTransaction(nexusUserId) + val nexusUser = extractNexusUser(nexusUserId) val subscriber = getEbicsSubscriberFromUser(nexusUser) val signPubTmp = CryptoUtil.getRsaPublicFromPrivate( CryptoUtil.loadRsaPrivateKey(subscriber.signaturePrivateKey.toByteArray()) @@ -592,7 +595,7 @@ fun main() { post("/ebics/subscribers/{id}/backup") { val body = call.receive<EbicsBackupRequestJson>() val response = transaction { - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) + val nexusUser = extractNexusUser(call.parameters["id"]) val subscriber = getEbicsSubscriberFromUser(nexusUser) EbicsKeysBackupJson( userID = subscriber.userID, @@ -628,7 +631,7 @@ fun main() { /** Download keys from bank */ post("/ebics/subscribers/{id}/sync") { - val nexusUser = expectNexusIdTransaction(call.parameters["id"]) + val nexusUser = extractNexusUser(call.parameters["id"]) val subscriberDetails = getSubscriberDetailsFromNexusUserId(nexusUser.id.value) val hpbRequest = makeEbicsHpbRequest(subscriberDetails) val responseStr = client.postToBank(subscriberDetails.ebicsUrl, hpbRequest) @@ -731,7 +734,7 @@ fun main() { * calling EBICS subscriber. */ post("/ebics/subscribers/{id}/fetch-accounts") { - val nexusUser = expectNexusIdTransaction((call.parameters["id"])) + val nexusUser = extractNexusUser((call.parameters["id"])) val paramsJson = call.receive<EbicsStandardOrderParamsJson>() val orderParams = paramsJson.toOrderParams() val subscriberData = getSubscriberDetailsFromNexusUserId(nexusUser.id.value) @@ -831,7 +834,10 @@ fun main() { if (resp.technicalReturnCode != EbicsReturnCode.EBICS_OK) { throw NexusError(HttpStatusCode.InternalServerError,"Unexpected INI response code: ${resp.technicalReturnCode}") } - call.respondText("Bank accepted signature key\n", ContentType.Text.Plain, HttpStatusCode.OK) + call.respondText( + "Bank accepted signature key\n", + ContentType.Text.Plain, HttpStatusCode.OK + ) return@post } @@ -860,7 +866,6 @@ fun main() { Taler(this) } } - logger.info("Up and running") server.start(wait = true) } \ No newline at end of file diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt @@ -16,10 +16,8 @@ import org.jetbrains.exposed.dao.IdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction import org.joda.time.DateTime -import org.joda.time.format.DateTimeFormat import tech.libeufin.util.Amount import tech.libeufin.util.CryptoUtil -import tech.libeufin.util.toZonedString import kotlin.math.abs import kotlin.math.min @@ -242,7 +240,7 @@ class Taler(app: Route) { val opaque_row_id = transaction { val creditorData = parsePayto(transferRequest.credit_account) val exchangeBankAccount = getBankAccountFromNexusUserId(exchangeId) - val nexusUser = expectNexusIdTransaction(exchangeId) + val nexusUser = extractNexusUser(exchangeId) /** * Checking the UID has the desired characteristics. */ @@ -545,7 +543,7 @@ class Taler(app: Route) { iban = "42" bankCode = "localhost" } - val nexusUser = expectNexusIdTransaction(exchangeId) + val nexusUser = extractNexusUser(exchangeId) EbicsToBankAccountEntity.new { bankAccount = newBankAccount ebicsSubscriber = getEbicsSubscriberFromUser(nexusUser)