gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated (8868572 -> c98ef14)


From: gnunet
Subject: [libeufin] branch master updated (8868572 -> c98ef14)
Date: Wed, 06 Nov 2019 11:02:44 +0100

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

marcello pushed a change to branch master
in repository libeufin.

    from 8868572  HTD order type JAXB and test
     new 9bdeeec  Implement /ebics/subscribers (nexus).
     new d44eef4  craft INI message to send (nexus)
     new a61adff  use the ".apply {}" notation
     new aed6728  nexus POSTs INI (hits invalid XML for now)
     new f85b013  get INI to validate
     new c98ef14  make systemID nullable + catch != 200 responses (nexus)

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 nexus/build.gradle                                 |   1 +
 nexus/src/main/kotlin/DB.kt                        |  42 +++-
 nexus/src/main/kotlin/JSON.kt                      |  27 +++
 nexus/src/main/kotlin/Main.kt                      | 214 ++++++++++++++++++++-
 .../src/main/kotlin/tech/libeufin/sandbox/JSON.kt  |   1 -
 5 files changed, 282 insertions(+), 3 deletions(-)
 create mode 100644 nexus/src/main/kotlin/JSON.kt

diff --git a/nexus/build.gradle b/nexus/build.gradle
index 5f93162..04c7f1c 100644
--- a/nexus/build.gradle
+++ b/nexus/build.gradle
@@ -32,6 +32,7 @@ dependencies {
     implementation group: 'xerces', name: 'xercesImpl', version: 
'2.6.2-jaxb-1.0.6'
     implementation "javax.activation:activation:1.1"
     implementation "org.glassfish.jaxb:jaxb-runtime:2.3.1"
+    implementation 'org.apache.santuario:xmlsec:2.1.4'
 
     testImplementation group: 'junit', name: 'junit', version: '4.12'
 }
diff --git a/nexus/src/main/kotlin/DB.kt b/nexus/src/main/kotlin/DB.kt
index 63d1e6b..ac61792 100644
--- a/nexus/src/main/kotlin/DB.kt
+++ b/nexus/src/main/kotlin/DB.kt
@@ -2,4 +2,44 @@ 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.ThreadLocalTransactionManager
+import org.jetbrains.exposed.sql.transactions.TransactionManager
+import org.jetbrains.exposed.sql.transactions.transaction
+import tech.libeufin.sandbox.EbicsHosts
+import java.sql.Connection
+
+object EbicsSubscribersTable: IntIdTable() {
+    val ebicsURL = text("ebicsURL")
+    val hostID = text("hostID")
+    val partnerID = text("partnerID")
+    val userID = text("userID")
+    val systemID = text("systemID").nullable()
+    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
new file mode 100644
index 0000000..4b6c66b
--- /dev/null
+++ 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
index 07c2efd..c6bdd27 100644
--- a/nexus/src/main/kotlin/Main.kt
+++ b/nexus/src/main/kotlin/Main.kt
@@ -19,32 +19,244 @@
 
 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.client.request.post
+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.http.URLBuilder
+import io.ktor.http.takeFrom
+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.*
+import tech.libeufin.schema.ebics_h004.EbicsKeyManagementResponse
+import tech.libeufin.schema.ebics_h004.EbicsUnsecuredRequest
+import tech.libeufin.schema.ebics_h004.OrderDetails
+import tech.libeufin.schema.ebics_h004.StaticHeader
+import tech.libeufin.schema.ebics_s001.PubKeyValueType
+import tech.libeufin.schema.ebics_s001.SignaturePubKeyInfoType
+import tech.libeufin.schema.ebics_s001.SignaturePubKeyOrderData
+import java.text.DateFormat
+import javax.sql.rowset.serial.SerialBlob
+
+fun testData() {
+
+    val pairA = CryptoUtil.generateRsaKeyPair(2048)
+    val pairB = CryptoUtil.generateRsaKeyPair(2048)
+    val pairC = CryptoUtil.generateRsaKeyPair(2048)
+
+    transaction {
+        EbicsSubscriberEntity.new {
+            ebicsURL = "http://localhost:5000/ebicsweb";
+            userID = "USER1"
+            partnerID = "PARTNER1"
+            hostID = "host01"
+
+            signaturePrivateKey = SerialBlob(pairA.private.encoded)
+            encryptionPrivateKey = SerialBlob(pairB.private.encoded)
+            authenticationPrivateKey = SerialBlob(pairC.private.encoded)
+        }
+    }
+}
 
 
 fun main() {
+    dbCreateTables()
+    testData() // gets always id == 1
+    val client = HttpClient()
+
     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("/ebics/subscribers/{id}/sendIni") {
+                // empty body for now..?
+                val id = try {
+                    call.parameters["id"]!!.toInt()
+
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    call.respond(
+                        HttpStatusCode.BadRequest,
+                        NexusError(e.message.toString())
+                    )
+                    return@post
+                }
+
+                val iniRequest = EbicsUnsecuredRequest()
+
+                val url = transaction {
+                    val subscriber = EbicsSubscriberEntity.findById(id)
+                    val tmpKey = 
CryptoUtil.loadRsaPrivateKey(subscriber!!.signaturePrivateKey.toByteArray())
+
+                    iniRequest.apply {
+                        version = "H004"
+                        revision = 1
+                        header = EbicsUnsecuredRequest.Header().apply {
+                            authenticate = true
+                            static = StaticHeader().apply {
+                                orderDetails = OrderDetails().apply {
+                                    orderAttribute = "DZNNN"
+                                    orderType = "INI"
+                                    securityMedium = "0000"
+                                    hostID = subscriber!!.hostID
+                                    userID = subscriber!!.userID
+                                    partnerID = subscriber!!.partnerID
+                                    systemID = subscriber!!.systemID
+                                }
+
+                            }
+                            mutable = 
EbicsUnsecuredRequest.Header.EmptyMutableHeader()
+                        }
+                        body = EbicsUnsecuredRequest.Body().apply {
+                            dataTransfer = 
EbicsUnsecuredRequest.Body.UnsecuredDataTransfer().apply {
+                                orderData = 
EbicsUnsecuredRequest.Body.UnsecuredDataTransfer.OrderData().apply {
+                                    value = EbicsOrderUtil.encodeOrderDataXml(
+                                        SignaturePubKeyOrderData().apply {
+                                            signaturePubKeyInfo = 
SignaturePubKeyInfoType().apply {
+                                                signatureVersion = "A006"
+                                                pubKeyValue = 
PubKeyValueType().apply {
+                                                    rsaKeyValue = 
org.apache.xml.security.binding.xmldsig.RSAKeyValueType().apply {
+                                                        exponent = 
tmpKey.publicExponent.toByteArray()
+                                                        modulus = 
tmpKey.modulus.toByteArray()
+                                                    }
+                                                }
+                                            }
+                                            userID = subscriber.userID
+                                            partnerID = subscriber.partnerID
+
+                                        }
+                                    )
+                                }
+                            }
+                        }
+                    }
+                    subscriber!!.ebicsURL
+                }
+
+                if (iniRequest == null) {
+                    call.respond(
+                        HttpStatusCode.NotFound,
+                        NexusError("Could not find that subscriber")
+                    )
+                    return@post
+                }
+
+                logger.info("POSTing to ${url}")
+
+                val response = try {
+                    client.post<String>(
+                        urlString = url,
+                        block = {
+                            body = XMLUtil.convertJaxbToString(iniRequest)
+                        }
+                    )
+                } catch (e: Exception) {
+                    e.printStackTrace()
+
+                    call.respond(
+                        HttpStatusCode.OK,
+                        NexusError("Exception thrown by HTTP client (likely 
server responded != 200).")
+                    )
+                    return@post
+                }
+
+                /**
+                 * TODO: check response status code,
+                 * and act accordingly when it differs from 200.
+                 */
+
+                // works: val responseJaxb = 
XMLUtil.convertStringToJaxb<EbicsKeyManagementResponse>(response)
+
+                call.respond(
+                    HttpStatusCode.OK,
+                    NexusError("Sandbox responded.")
+                )
+                return@post
+            }
+
             post("/nexus") {
-                val client = HttpClient()
+
                 val content = try {
                     client.get<ByteArray>(
                         "https://ebicstest1.libeufin.tech/";
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
index 157db79..428b9c4 100644
--- 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
  */

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



reply via email to

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