libeufin

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

commit 9bdeeece0972df4376997ef1f6ab1b9e046d1403
parent 886857244fa220352d9f9745a2e3401a2436a770
Author: Marcello Stanisci <stanisci.m@gmail.com>
Date:   Tue,  5 Nov 2019 17:38:18 +0100

Implement /ebics/subscribers (nexus).

This includes the three keypairs generation.

Diffstat:
Mnexus/src/main/kotlin/DB.kt | 41+++++++++++++++++++++++++++++++++++++++--
Anexus/src/main/kotlin/JSON.kt | 28++++++++++++++++++++++++++++
Mnexus/src/main/kotlin/Main.kt | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt | 1-
4 files changed, 144 insertions(+), 3 deletions(-)

diff --git a/nexus/src/main/kotlin/DB.kt b/nexus/src/main/kotlin/DB.kt @@ -2,4 +2,41 @@ package tech.libeufin.nexus import org.jetbrains.exposed.dao.* import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.transactions.transaction -\ No newline at end of file +import org.jetbrains.exposed.sql.transactions.transaction +import tech.libeufin.sandbox.EbicsHosts + +object EbicsSubscribersTable: IntIdTable() { + val ebicsURL = text("ebicsURL") + val hostID = text("hostID") + val partnerID = text("partnerID") + val userID = text("userID") + val systemID = text("systemID") + val signaturePrivateKey = blob("signaturePrivateKey") + val encryptionPrivateKey = blob("encryptionPrivateKey") + val authenticationPrivateKey = blob("authenticationPrivateKey") +} + +class EbicsSubscriberEntity(id: EntityID<Int>) : IntEntity(id) { + companion object : IntEntityClass<EbicsSubscriberEntity>(EbicsSubscribersTable) + + var ebicsURL by EbicsSubscribersTable.ebicsURL + var hostID by EbicsSubscribersTable.hostID + var partnerID by EbicsSubscribersTable.partnerID + var userID by EbicsSubscribersTable.userID + var systemID by EbicsSubscribersTable.systemID + var signaturePrivateKey by EbicsSubscribersTable.signaturePrivateKey + var encryptionPrivateKey by EbicsSubscribersTable.encryptionPrivateKey + var authenticationPrivateKey by EbicsSubscribersTable.authenticationPrivateKey +} + +fun dbCreateTables() { + Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver") + + transaction { + // addLogger(StdOutSqlLogger) + + SchemaUtils.create( + EbicsSubscribersTable + ) + } +} +\ No newline at end of file diff --git a/nexus/src/main/kotlin/JSON.kt b/nexus/src/main/kotlin/JSON.kt @@ -0,0 +1,27 @@ +package tech.libeufin.nexus + +/** + * This object is POSTed by clients _after_ having created + * a EBICS subscriber at the sandbox. + */ +data class EbicsSubscriberInfoRequest( + val ebicsURL: String, + val hostID: String, + val partnerID: String, + val userID: String, + val systemID: String +) + +/** + * Contain the ID that identifies the new user in the Nexus system. + */ +data class EbicsSubscriberInfoResponse( + val accountID: Number +) + +/** + * Error message. + */ +data class NexusError( + val message: String +) +\ No newline at end of file diff --git a/nexus/src/main/kotlin/Main.kt b/nexus/src/main/kotlin/Main.kt @@ -19,30 +19,107 @@ package tech.libeufin.nexus +import io.ktor.application.ApplicationCallPipeline import io.ktor.application.call +import io.ktor.application.install import io.ktor.client.* import io.ktor.client.features.ServerResponseException import io.ktor.client.request.get +import io.ktor.features.ContentNegotiation +import io.ktor.features.StatusPages +import io.ktor.gson.gson +import io.ktor.http.ContentType +import io.ktor.http.HttpStatusCode +import io.ktor.request.receive +import io.ktor.request.uri +import io.ktor.response.respond import io.ktor.response.respondText import io.ktor.routing.get import io.ktor.routing.post import io.ktor.routing.routing import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty +import org.jetbrains.exposed.sql.transactions.transaction import org.slf4j.LoggerFactory +import tech.libeufin.sandbox.CryptoUtil +import tech.libeufin.sandbox.EbicsSubscribers +import tech.libeufin.sandbox.SandboxError +import java.text.DateFormat +import javax.sql.rowset.serial.SerialBlob fun main() { + dbCreateTables() val logger = LoggerFactory.getLogger("tech.libeufin.nexus") val server = embeddedServer(Netty, port = 5001) { + install(ContentNegotiation) { + gson { + setDateFormat(DateFormat.LONG) + setPrettyPrinting() + } + } + install(StatusPages) { + exception<Throwable> { cause -> + tech.libeufin.sandbox.logger.error("Exception while handling '${call.request.uri}'", cause) + call.respondText("Internal server error.", ContentType.Text.Plain, HttpStatusCode.InternalServerError) + } + } + + intercept(ApplicationCallPipeline.Fallback) { + if (this.call.response.status() == null) { + call.respondText("Not found (no route matched).\n", ContentType.Text.Plain, HttpStatusCode.NotFound) + return@intercept finish() + } + } + routing { get("/") { call.respondText("Hello by Nexus!\n") return@get } + post("/ebics/subscribers") { + val body = try { + call.receive<EbicsSubscriberInfoRequest>() + } catch (e: Exception) { + e.printStackTrace() + call.respond( + HttpStatusCode.BadRequest, + NexusError(e.message.toString()) + ) + return@post + } + + val pairA = CryptoUtil.generateRsaKeyPair(2048) + val pairB = CryptoUtil.generateRsaKeyPair(2048) + val pairC = CryptoUtil.generateRsaKeyPair(2048) + + val id = transaction { + + + EbicsSubscriberEntity.new { + ebicsURL = body.ebicsURL + hostID = body.hostID + partnerID = body.partnerID + userID = body.userID + systemID = body.systemID + signaturePrivateKey = SerialBlob(pairA.private.encoded) + encryptionPrivateKey = SerialBlob(pairB.private.encoded) + authenticationPrivateKey = SerialBlob(pairC.private.encoded) + + }.id.value + } + + call.respond( + HttpStatusCode.OK, + EbicsSubscriberInfoResponse(id) + ) + + return@post + } + post("/nexus") { val client = HttpClient() val content = try { diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt @@ -26,7 +26,6 @@ data class SandboxError( val message: String ) - /** * Request for POST /admin/customers */