diff options
author | Marcello Stanisci <ms@taler.net> | 2020-05-12 16:15:55 +0200 |
---|---|---|
committer | Marcello Stanisci <ms@taler.net> | 2020-05-12 16:15:55 +0200 |
commit | 2d656c1d85ac443519b7f07c11b6b52744146838 (patch) | |
tree | bb1db280696560424976653080663d397e5790cc /nexus/src/main | |
parent | 85ffd4121387669dc5570231d2adb6ff40124eee (diff) | |
download | libeufin-2d656c1d85ac443519b7f07c11b6b52744146838.tar.gz libeufin-2d656c1d85ac443519b7f07c11b6b52744146838.tar.bz2 libeufin-2d656c1d85ac443519b7f07c11b6b52744146838.zip |
implement /sync{MSG}
Diffstat (limited to 'nexus/src/main')
4 files changed, 85 insertions, 36 deletions
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt index 1826ae33..4258b844 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt @@ -1,6 +1,5 @@ package tech.libeufin.nexus -import io.ktor.application.ApplicationCall import io.ktor.client.HttpClient import io.ktor.http.HttpStatusCode import org.jetbrains.exposed.sql.and @@ -101,7 +100,7 @@ fun getBankAccountsFromNexusUserId(id: String): MutableList<BankAccountEntity> { return ret } -fun getSubscriberDetails(subscriber: EbicsSubscriberEntity): EbicsClientSubscriberDetails { +fun getEbicsSubscriberDetailsInternal(subscriber: EbicsSubscriberEntity): EbicsClientSubscriberDetails { var bankAuthPubValue: RSAPublicKey? = null if (subscriber.bankAuthenticationPublicKey != null) { bankAuthPubValue = CryptoUtil.loadRsaPublicKey( @@ -129,11 +128,7 @@ fun getSubscriberDetails(subscriber: EbicsSubscriberEntity): EbicsClientSubscrib ) } -/** - * Retrieve Ebics subscriber details given a Transport - * object and handling the default case. - */ -fun getEbicsSubscriberDetails(userId: String, transportId: String?): EbicsClientSubscriberDetails { +fun getEbicsTransport(userId: String, transportId: String?): EbicsSubscriberEntity { val transport = transaction { if (transportId == null) { return@transaction EbicsSubscriberEntity.all().first() @@ -150,8 +145,17 @@ fun getEbicsSubscriberDetails(userId: String, transportId: String?): EbicsClient "No rights over transport $transportId" ) } + return transport +} + +/** + * Retrieve Ebics subscriber details given a Transport + * object and handling the default case. + */ +fun getEbicsSubscriberDetails(userId: String, transportId: String?): EbicsClientSubscriberDetails { + val transport = getEbicsTransport(userId, transportId) // transport exists and belongs to caller. - return getSubscriberDetails(transport) + return getEbicsSubscriberDetailsInternal(transport) } suspend fun downloadAndPersistC5xEbics( @@ -394,8 +398,10 @@ fun addPreparedPayment(paymentData: Pain001Data, nexusUser: NexusUserEntity): Pr } } -fun expectId(param: String?): String { - return param ?: throw NexusError(HttpStatusCode.BadRequest, "Bad ID given") +fun ensureNonNull(param: String?): String { + return param ?: throw NexusError( + HttpStatusCode.BadRequest, "Bad ID given" + ) } /* Needs a transaction{} block to be called */ diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt index 234d239a..793ba532 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt @@ -50,7 +50,6 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level import tech.libeufin.util.* -import tech.libeufin.util.ebics_h004.EbicsResponse import java.text.DateFormat import java.util.zip.InflaterInputStream import javax.crypto.EncryptedPrivateKeyInfo @@ -59,18 +58,25 @@ import javax.sql.rowset.serial.SerialBlob data class NexusError(val statusCode: HttpStatusCode, val reason: String) : Exception() val logger: Logger = LoggerFactory.getLogger("tech.libeufin.nexus") -suspend fun handleEbicsSendMSG(client: HttpClient, subscriber: EbicsClientSubscriberDetails, msg: String): String { - when (msg.toUpperCase()) { +suspend fun handleEbicsSendMSG( + httpClient: HttpClient, + userId: String, + transportId: String?, + msg: String, + sync: Boolean +): String { + val subscriber = getEbicsSubscriberDetails(userId, transportId) + val response = when (msg.toUpperCase()) { "HIA" -> { val request = makeEbicsHiaRequest(subscriber) - return client.postToBank( + httpClient.postToBank( subscriber.ebicsUrl, request ) } "INI" -> { val request = makeEbicsIniRequest(subscriber) - return client.postToBank( + httpClient.postToBank( subscriber.ebicsUrl, request ) @@ -78,20 +84,35 @@ suspend fun handleEbicsSendMSG(client: HttpClient, subscriber: EbicsClientSubscr "HPB" -> { /** should NOT put bank's keys into any table. */ val request = makeEbicsHpbRequest(subscriber) - return client.postToBank( + val response = httpClient.postToBank( subscriber.ebicsUrl, request ) + if (sync) { + val parsedResponse = parseAndDecryptEbicsKeyManagementResponse(subscriber, response) + val orderData = parsedResponse.orderData ?: throw NexusError( + HttpStatusCode.InternalServerError, + "Cannot find data in a HPB response" + ) + val hpbData = parseEbicsHpbOrder(orderData) + transaction { + val transport = getEbicsTransport(userId, transportId) + transport.bankAuthenticationPublicKey = SerialBlob(hpbData.authenticationPubKey.encoded) + transport.bankEncryptionPublicKey = SerialBlob(hpbData.encryptionPubKey.encoded) + } + } + return response } "HEV" -> { val request = makeEbicsHEVRequest(subscriber) - return client.postToBank(subscriber.ebicsUrl, request) + httpClient.postToBank(subscriber.ebicsUrl, request) } else -> throw NexusError( HttpStatusCode.NotFound, "Message $msg not found" ) } + return response } @ExperimentalIoApi @@ -260,7 +281,7 @@ fun main() { */ get("/bank-accounts/{accountid}/prepared-payments/{uuid}") { val userId = authenticateRequest(call.request.headers["Authorization"]) - val preparedPayment = getPreparedPayment(expectId(call.parameters["uuid"])) + val preparedPayment = getPreparedPayment(ensureNonNull(call.parameters["uuid"])) if (preparedPayment.nexusUser.id.value != userId) throw NexusError( HttpStatusCode.Forbidden, "No rights over such payment" @@ -285,7 +306,7 @@ fun main() { */ post("/bank-accounts/{accountid}/prepared-payments") { val userId = authenticateRequest(call.request.headers["Authorization"]) - val bankAccount = getBankAccount(userId, expectId(call.parameters["accountid"])) + val bankAccount = getBankAccount(userId, ensureNonNull(call.parameters["accountid"])) val body = call.receive<PreparedPaymentRequest>() val amount = parseAmount(body.amount) val paymentEntity = addPreparedPayment( @@ -474,9 +495,12 @@ fun main() { when (body.type) { "ebics" -> { val response = handleEbicsSendMSG( - client, - getEbicsSubscriberDetails(userId, body.name), - expectId(call.parameters["MSG"])) + httpClient = client, + userId = userId, + transportId = body.name, + msg = ensureNonNull(call.parameters["MSG"]), + sync = true + ) call.respondText(response) } else -> throw NexusError( @@ -491,6 +515,25 @@ fun main() { * "transportName". DOES alterate DB tables. */ post("/bank-transports/{transportName}/sync{MSG}") { + val userId = authenticateRequest(call.request.headers["Authorization"]) + val body = call.receive<Transport>() + when (body.type) { + "ebics" -> { + val response = handleEbicsSendMSG( + httpClient = client, + userId = userId, + transportId = body.name, + msg = ensureNonNull(call.parameters["MSG"]), + sync = true + ) + call.respondText(response) + } + else -> throw NexusError( + HttpStatusCode.NotImplemented, + "Transport '${body.type}' not implemented. Use 'ebics'" + ) + } + return@post } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/MainDeprecated.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/MainDeprecated.kt index df00d65c..d730001a 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/MainDeprecated.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/MainDeprecated.kt @@ -202,7 +202,7 @@ fun main() { } /** Make a new NEXUS user in the system */ post("/users/{id}") { - val newUserId = expectId(call.parameters["id"]) + val newUserId = ensureNonNull(call.parameters["id"]) val body = call.receive<NexusUserRequest>() transaction { NexusUserEntity.new(id = newUserId) { @@ -224,7 +224,7 @@ fun main() { /** Show bank accounts associated with a given NEXUS user */ get("/users/{id}/accounts") { // this information is only avaiable *after* HTD or HKD has been called - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val ret = BankAccountsInfoResponse() transaction { BankAccountMapEntity.find { @@ -248,7 +248,7 @@ fun main() { } /** Show PREPARED payments */ get("/users/{id}/payments") { - val nexusUserId = expectId(call.parameters["id"]) + val nexusUserId = ensureNonNull(call.parameters["id"]) val ret = RawPayments() transaction { val nexusUser = extractNexusUser(nexusUserId) @@ -345,7 +345,7 @@ fun main() { } post("/ebics/subscribers/{id}/restoreBackup") { val body = call.receive<EbicsKeysBackupJson>() - val nexusId = expectId(call.parameters["id"]) + val nexusId = ensureNonNull(call.parameters["id"]) val subscriber = transaction { NexusUserEntity.findById(nexusId) } @@ -425,7 +425,7 @@ fun main() { ) } get("/ebics/subscribers/{id}/keyletter") { - val nexusUserId = expectId(call.parameters["id"]) + val nexusUserId = ensureNonNull(call.parameters["id"]) var usernameLine = "TODO" var recipientLine = "TODO" val customerIdLine = "TODO" @@ -572,7 +572,7 @@ fun main() { logger.debug("Uploading PAIN.001: ${painDoc}") doEbicsUploadTransaction( client, - getSubscriberDetails(subscriber), + getEbicsSubscriberDetailsInternal(subscriber), "CCT", painDoc.toByteArray(Charsets.UTF_8), EbicsStandardOrderParams() @@ -651,7 +651,7 @@ fun main() { return@post } post("/ebics/subscribers/{id}/fetch-payment-status") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val paramsJson = call.receive<EbicsStandardOrderParamsJson>() val orderParams = paramsJson.toOrderParams() val subscriberData = getSubscriberDetailsFromNexusUserId(id) @@ -677,7 +677,7 @@ fun main() { return@post } post("/ebics/subscribers/{id}/collect-transactions-c53") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val paramsJson = call.receive<EbicsStandardOrderParamsJson>() val orderParams = paramsJson.toOrderParams() val subscriberData = getSubscriberDetailsFromNexusUserId(id) @@ -778,8 +778,8 @@ fun main() { // FIXME: some messages include a ZIPped payload. post("/ebics/subscribers/{id}/send{MSG}") { - val id = expectId(call.parameters["id"]) - val MSG = expectId(call.parameters["MSG"]) + val id = ensureNonNull(call.parameters["id"]) + val MSG = ensureNonNull(call.parameters["MSG"]) val paramsJson = call.receive<EbicsStandardOrderParamsJson>() val orderParams = paramsJson.toOrderParams() println("$MSG order params: $orderParams") @@ -808,7 +808,7 @@ fun main() { return@post } get("/ebics/{id}/sendHEV") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val subscriberData = getSubscriberDetailsFromNexusUserId(id) val request = makeEbicsHEVRequest(subscriberData) val response = client.postToBank(subscriberData.ebicsUrl, request) @@ -825,7 +825,7 @@ fun main() { return@get } post("/ebics/subscribers/{id}/sendINI") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val subscriberData = getSubscriberDetailsFromNexusUserId(id) val iniRequest = makeEbicsIniRequest(subscriberData) val responseStr = client.postToBank( @@ -844,7 +844,7 @@ fun main() { } post("/ebics/subscribers/{id}/sendHIA") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) val subscriberData = getSubscriberDetailsFromNexusUserId(id) val hiaRequest = makeEbicsHiaRequest(subscriberData) val responseStr = client.postToBank( diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt index 8a97107d..b259bb51 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt @@ -395,7 +395,7 @@ class Taler(app: Route) { * payment was added as well. */ app.post("/ebics/taler/{id}/crunch-raw-transactions") { - val id = expectId(call.parameters["id"]) + val id = ensureNonNull(call.parameters["id"]) // first find highest ID value of already processed rows. transaction { val subscriberAccount = getBankAccountFromNexusUserId(id) |