[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (7677c4f1 -> 5d537b70)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (7677c4f1 -> 5d537b70) |
Date: |
Mon, 14 Feb 2022 10:16:06 +0100 |
This is an automated email from the git hooks/post-receive script.
ms pushed a change to branch master
in repository libeufin.
from 7677c4f1 optionally collecting IBAN along registration
new 3e204b0b Setting JSON request parser as the default.
new 5d537b70 Setting JSON request parser as the default.
The 2 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:
.../tech/libeufin/nexus/ebics/EbicsClient.kt | 5 ++-
.../tech/libeufin/sandbox/EbicsProtocolBackend.kt | 48 +++++++++++++--------
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 48 +++++++++------------
.../tech/libeufin/sandbox/XMLEbicsConverter.kt | 49 ++++++++++++++++++++++
4 files changed, 103 insertions(+), 47 deletions(-)
create mode 100644
sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
index f0242ceb..fdacdeb7 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsClient.kt
@@ -24,8 +24,9 @@ package tech.libeufin.nexus.ebics
import io.ktor.client.HttpClient
import io.ktor.client.features.*
-import io.ktor.client.request.post
-import io.ktor.http.HttpStatusCode
+import io.ktor.client.request.*
+import io.ktor.http.*
+import io.ktor.util.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import tech.libeufin.nexus.NexusError
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index 0594e934..cda505ab 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -23,7 +23,7 @@ package tech.libeufin.sandbox
import io.ktor.application.*
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
-import io.ktor.request.receiveText
+import io.ktor.request.*
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.util.AttributeKey
@@ -33,8 +33,6 @@ import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
import org.jetbrains.exposed.sql.transactions.transaction
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
import org.w3c.dom.Document
import tech.libeufin.util.*
import tech.libeufin.util.XMLUtil.Companion.signEbicsResponse
@@ -46,8 +44,6 @@ import tech.libeufin.util.ebics_s001.UserSignatureData
import java.math.BigDecimal
import java.security.interfaces.RSAPrivateCrtKey
import java.security.interfaces.RSAPublicKey
-import java.time.Instant
-import java.time.LocalDateTime
import java.util.*
import java.util.zip.DeflaterInputStream
import java.util.zip.InflaterInputStream
@@ -124,6 +120,21 @@ suspend fun respondEbicsTransfer(
errorText: String,
errorCode: String
) {
+ /**
+ * Because this handler runs for any error, it could
+ * handle the case where the Ebics host ID is unknown due
+ * to an invalid request. Recall: Sandbox is multi-host, and
+ * which Ebics host was requested belongs to the request document.
+ *
+ * Therefore, because any (? Please verify!) Ebics response
+ * should speak for one Ebics host, we won't respond any Ebics
+ * type when the Ebics host ID remains unknown due to invalid
+ * request. Instead, we'll respond plain text:
+ */
+ if (!call.attributes.contains(EbicsHostIdAttribute)) {
+ call.respondText("Invalid document.", status =
HttpStatusCode.BadRequest)
+ return
+ }
val resp = EbicsResponse.createForUploadWithError(
errorText,
errorCode,
@@ -935,7 +946,7 @@ private suspend fun ApplicationCall.handleEbicsHpb(
/**
* Find the ebics host corresponding to the one specified in the header.
*/
-private fun ApplicationCall.ensureEbicsHost(requestHostID: String):
EbicsHostPublicInfo {
+private fun ensureEbicsHost(requestHostID: String): EbicsHostPublicInfo {
return transaction {
val ebicsHost =
EbicsHostEntity.find { EbicsHostsTable.hostID.upperCase() eq
requestHostID.uppercase(Locale.getDefault()) }.firstOrNull()
@@ -952,22 +963,19 @@ private fun
ApplicationCall.ensureEbicsHost(requestHostID: String): EbicsHostPub
)
}
}
-
-private suspend fun ApplicationCall.receiveEbicsXml(): Document {
- val body: String = receiveText()
- logger.debug("Data received: $body")
- val requestDocument: Document? = XMLUtil.parseStringIntoDom(body)
+fun receiveEbicsXmlInternal(xmlData: String): Document {
+ logger.debug("Data received: $xmlData")
+ val requestDocument: Document? = XMLUtil.parseStringIntoDom(xmlData)
if (requestDocument == null ||
(!XMLUtil.validateFromDom(requestDocument))) {
println("Problematic document was: $requestDocument")
throw EbicsInvalidXmlError()
}
- val requestedHostID = requestDocument.getElementsByTagName("HostID")
- this.attributes.put(
- EbicsHostIdAttribute,
- requestedHostID.item(0).textContent
- )
return requestDocument
}
+suspend fun ApplicationCall.receiveEbicsXml(): Document {
+ val body: String = receiveText()
+ return receiveEbicsXmlInternal(body)
+}
private fun makePartnerInfo(subscriber: EbicsSubscriberEntity):
EbicsTypes.PartnerInfo {
val bankAccount = getBankAccountFromSubscriber(subscriber)
@@ -1324,7 +1332,13 @@ private fun makeRequestContext(requestObject:
EbicsRequest): RequestContext {
}
suspend fun ApplicationCall.ebicsweb() {
- val requestDocument = receiveEbicsXml()
+ val requestDocument = this.request.call.receive<Document>()
+ val requestedHostID = requestDocument.getElementsByTagName("HostID")
+ this.attributes.put(
+ EbicsHostIdAttribute,
+ requestedHostID.item(0).textContent
+ )
+ // val requestDocument = receiveEbicsXml()
logger.info("Processing ${requestDocument.documentElement.localName}")
when (requestDocument.documentElement.localName) {
"ebicsUnsecuredRequest" -> {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index ca4a0db3..caf8167a 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -370,11 +370,6 @@ inline fun <reified T> Document.toObject(): T {
return m.unmarshal(this, T::class.java).value
}
-fun BigDecimal.signToString(): String {
- return if (this.signum() > 0) "+" else ""
- // minus sign is added by default already.
-}
-
fun ensureNonNull(param: String?): String {
return param ?: throw SandboxError(
HttpStatusCode.BadRequest, "Bad ID given: $param"
@@ -426,25 +421,22 @@ val sandboxApp: Application.() -> Unit = {
logger.info("Enabling CORS (assuming no endpoint uses cookies).")
allowCredentials = true
}
- install(Authentication) {
- // Web-based authentication for Bank customers.
- form("auth-form") {
- userParamName = "username"
- passwordParamName = "password"
- validate { credentials ->
- if (credentials.name == "test") {
- UserIdPrincipal(credentials.name)
- } else {
- null
- }
- }
- }
- }
install(ContentNegotiation) {
- jackson {
+ register(ContentType.Text.Xml, XMLEbicsConverter())
+ /**
+ * Content type "text" must go to the XML parser
+ * because Nexus can't set explicitly the Content-Type
+ * (see https://github.com/ktorio/ktor/issues/1127) to
+ * "xml" and the request made gets somehow assigned the
+ * "text/plain" type: */
+ register(ContentType.Text.Plain, XMLEbicsConverter())
+ /**
+ * Make jackson the default parser. It runs also when
+ * the Content-Type request header is missing. */
+ jackson(contentType = ContentType.Any) {
enable(com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT)
setDefaultPrettyPrinter(DefaultPrettyPrinter().apply {
-
indentArraysWith(com.fasterxml.jackson.core.util.DefaultPrettyPrinter.FixedSpaceIndenter.instance)
+
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
indentObjectsWith(DefaultIndenter(" ", "\n"))
})
registerModule(KotlinModule(nullisSameAsDefault = true))
@@ -493,8 +485,8 @@ val sandboxApp: Application.() -> Unit = {
logger.error("Exception while handling '${call.request.uri}'",
cause)
call.respondText(
"Internal server error.",
- io.ktor.http.ContentType.Text.Plain,
- io.ktor.http.HttpStatusCode.InternalServerError
+ ContentType.Text.Plain,
+ HttpStatusCode.InternalServerError
)
}
}
@@ -530,7 +522,10 @@ val sandboxApp: Application.() -> Unit = {
routing {
get("/") {
- call.respondText("Hello, this is the Sandbox\n",
ContentType.Text.Plain)
+ call.respondText(
+ "Hello, this is the Sandbox\n",
+ ContentType.Text.Plain
+ )
}
// Respond with the last statement of the requesting account.
@@ -937,9 +932,7 @@ val sandboxApp: Application.() -> Unit = {
}
catch (e: Exception) {
logger.error(e)
- if (e !is EbicsRequestError) {
- throw EbicsProcessingError("Unmanaged error: $e")
- }
+ throw EbicsProcessingError("Unmanaged error: $e")
}
return@post
}
@@ -990,7 +983,6 @@ val sandboxApp: Application.() -> Unit = {
call.respond(getJsonFromDemobankConfig(demobank))
return@get
}
-
route("/demobanks/{demobankid}") {
// NOTE: TWG assumes that username == bank account label.
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
new file mode 100644
index 00000000..64166daa
--- /dev/null
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt
@@ -0,0 +1,49 @@
+package tech.libeufin.sandbox
+
+import io.ktor.application.*
+import io.ktor.features.*
+import io.ktor.http.*
+import io.ktor.http.content.*
+import io.ktor.request.*
+import io.ktor.response.*
+import io.ktor.util.pipeline.*
+import io.ktor.utils.io.*
+import io.ktor.utils.io.jvm.javaio.*
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import tech.libeufin.util.XMLUtil
+import java.io.OutputStream
+import java.nio.channels.ByteChannel
+
+class XMLEbicsConverter : ContentConverter {
+ override suspend fun convertForReceive(
+ context: PipelineContext<ApplicationReceiveRequest, ApplicationCall>):
Any? {
+ val value = context.subject.value as? ByteReadChannel ?: return null
+ return withContext(Dispatchers.IO) {
+ receiveEbicsXmlInternal(value.toInputStream().reader().readText())
+ }
+ }
+ override suspend fun convertForSend(
+ context: PipelineContext<Any, ApplicationCall>,
+ contentType: ContentType,
+ value: Any
+ ): Any? {
+ val conv = try {
+ XMLUtil.convertJaxbToString(value)
+ } catch (e: Exception) {
+ /**
+ * Not always a error: the content negotiation might have
+ * only checked if this handler could convert the response.
+ */
+ logger.debug("Could not convert XML to string with custom
converter.")
+ return null
+ }
+ return OutputStreamContent({
+ val out = this;
+ withContext(Dispatchers.IO) {
+ out.write(conv.toByteArray())
+ }},
+ contentType.withCharset(context.call.suitableCharset())
+ )
+ }
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libeufin] branch master updated (7677c4f1 -> 5d537b70),
gnunet <=