[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated (9799d88 -> 8f11898)
From: |
gnunet |
Subject: |
[libeufin] branch master updated (9799d88 -> 8f11898) |
Date: |
Thu, 14 May 2020 17:49:53 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a change to branch master
in repository libeufin.
from 9799d88 Setup prettier for frontend
new 24d03f3 use generics for JSON type
new 8f11898 Overloading POST ../bank-transport.
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:
.idea/libeufin.iml | 2 +
nexus/build.gradle | 2 +-
.../src/main/kotlin/tech/libeufin/nexus/Helpers.kt | 21 ++-
nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt | 8 +-
nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 159 +++++++++++----------
nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 86 +++++------
nexus/src/test/kotlin/PainGeneration.kt | 2 -
nexus/src/test/kotlin/taler.kt | 10 +-
util/src/main/kotlin/ParametersChecks.kt | 7 +
9 files changed, 168 insertions(+), 129 deletions(-)
create mode 100644 .idea/libeufin.iml
diff --git a/.idea/libeufin.iml b/.idea/libeufin.iml
new file mode 100644
index 0000000..78b2cc5
--- /dev/null
+++ b/.idea/libeufin.iml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4" />
\ No newline at end of file
diff --git a/nexus/build.gradle b/nexus/build.gradle
index b2a264a..ff58a78 100644
--- a/nexus/build.gradle
+++ b/nexus/build.gradle
@@ -16,7 +16,7 @@ plugins {
sourceSets {
main.kotlin.srcDirs = ["src/main/kotlin"]
- main.kotlin.excludes = ["**/MainDeprecated.kt", "**/taler.kt"]
+ main.kotlin.excludes = ["**/MainDeprecated.kt"]
}
task installToPrefix(type: Copy) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 93e5eb9..135d53b 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -1,5 +1,7 @@
package tech.libeufin.nexus
+import com.google.gson.Gson
+import com.google.gson.JsonObject
import io.ktor.client.HttpClient
import io.ktor.http.HttpStatusCode
import org.jetbrains.exposed.sql.and
@@ -60,6 +62,12 @@ fun extractFirstBic(bankCodes:
List<EbicsTypes.AbstractBankCode>?): String? {
return null
}
+fun getTransportFromJsonObject(jo: JsonObject): Transport {
+ return Gson().fromJson(
+ expectNonNull(jo.get("transport")).asJsonObject, Transport::class.java
+ )
+}
+
/**
* Retrieve bank account details, only if user owns it.
*/
@@ -128,7 +136,7 @@ fun getEbicsSubscriberDetailsInternal(subscriber:
EbicsSubscriberEntity): EbicsC
)
}
-fun getEbicsTransport(userId: String, transportId: String?):
EbicsSubscriberEntity {
+fun getEbicsTransport(userId: String, transportId: String? = null):
EbicsSubscriberEntity {
val transport = transaction {
if (transportId == null) {
return@transaction EbicsSubscriberEntity.all().first()
@@ -150,7 +158,7 @@ fun getEbicsTransport(userId: String, transportId:
String?): EbicsSubscriberEnti
/**
* Retrieve Ebics subscriber details given a Transport
- * object and handling the default case.
+ * object and handling the default case (when this latter is null).
*/
fun getEbicsSubscriberDetails(userId: String, transportId: String?):
EbicsClientSubscriberDetails {
val transport = getEbicsTransport(userId, transportId)
@@ -370,6 +378,15 @@ fun getPreparedPayment(uuid: String):
PreparedPaymentEntity {
)
}
+fun getNexusUser(id: String): NexusUserEntity {
+ return transaction {
+ NexusUserEntity.findById(id)
+ } ?: throw NexusError(
+ HttpStatusCode.NotFound,
+ "User '$id' not found"
+ )
+}
+
/**
* Insert one row in the database, and leaves it marked as non-submitted.
* @param debtorAccountId the mnemonic id assigned by the bank to one bank
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
index 0b80677..8f27ec9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
@@ -1,8 +1,6 @@
package tech.libeufin.nexus
-import com.sun.jdi.connect.Transport
import tech.libeufin.util.*
-import java.lang.NullPointerException
import java.time.LocalDate
data class EbicsBackupRequestJson(
@@ -69,7 +67,7 @@ data class EbicsSubscriber(
val hostID: String,
val partnerID: String,
val userID: String,
- val systemID: String? = null
+ val systemID: String?
)
data class RawPayments(
@@ -80,8 +78,8 @@ data class RawPayments(
* API types (used as requests/responses types) *
*************************************************/
data class BankTransport(
- val transport: tech.libeufin.nexus.Transport,
- val backup: Any?,
+ val transport: Transport,
+ val backup: Any? = null,
val data: Any?
)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 488dce7..43db3b2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -19,6 +19,8 @@
package tech.libeufin.nexus
+import com.google.gson.Gson
+import com.google.gson.JsonObject
import io.ktor.application.ApplicationCallPipeline
import io.ktor.application.call
import io.ktor.application.install
@@ -404,88 +406,99 @@ fun main() {
post("/bank-transports") {
val userId =
authenticateRequest(call.request.headers["Authorization"])
// user exists and is authenticated.
- val body = call.receive<BankTransport>()
- logger.debug("Request body parsed")
- when (body.backup) {
- is EbicsKeysBackupJson -> {
- logger.debug("Restoring a transport:
${body.transport.name}")
- val (authKey, encKey, sigKey) = try {
- Triple(
- CryptoUtil.decryptKey(
-
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.authBlob)),
- body.backup.passphrase
- ),
- CryptoUtil.decryptKey(
-
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.encBlob)),
- body.backup.passphrase
- ),
- CryptoUtil.decryptKey(
-
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.sigBlob)),
- body.backup.passphrase
- )
- )
- } catch (e: Exception) {
- e.printStackTrace()
- logger.info("Restoring keys failed, probably due
to wrong passphrase")
- throw NexusError(
- HttpStatusCode.BadRequest,
- "Bad backup given"
+ val body = call.receive<JsonObject>()
+ val transport: Transport = getTransportFromJsonObject(body)
+ when (transport.type) {
+ "ebics" -> {
+ if (body.get("backup") != null) {
+ val backup = Gson().fromJson(
+ body.get("backup").asJsonObject,
+ EbicsKeysBackupJson::class.java
)
+ val (authKey, encKey, sigKey) = try {
+ Triple(
+ CryptoUtil.decryptKey(
+
EncryptedPrivateKeyInfo(base64ToBytes(backup.authBlob)),
+ backup.passphrase
+ ),
+ CryptoUtil.decryptKey(
+
EncryptedPrivateKeyInfo(base64ToBytes(backup.encBlob)),
+ backup.passphrase
+ ),
+ CryptoUtil.decryptKey(
+
EncryptedPrivateKeyInfo(base64ToBytes(backup.sigBlob)),
+ backup.passphrase
+ )
+ )
+ } catch (e: Exception) {
+ e.printStackTrace()
+ logger.info("Restoring keys failed, probably
due to wrong passphrase")
+ throw NexusError(
+ HttpStatusCode.BadRequest,
+ "Bad backup given"
+ )
+ }
+ logger.info("Restoring keys, creating new user:
$userId")
+ try {
+ transaction {
+ EbicsSubscriberEntity.new(transport.name) {
+ this.nexusUser =
extractNexusUser(userId)
+ ebicsURL = backup.ebicsURL
+ hostID = backup.hostID
+ partnerID = backup.partnerID
+ userID = backup.userID
+ signaturePrivateKey =
SerialBlob(sigKey.encoded)
+ encryptionPrivateKey =
SerialBlob(encKey.encoded)
+ authenticationPrivateKey =
SerialBlob(authKey.encoded)
+ }
+ }
+ } catch (e: Exception) {
+ print(e)
+ call.respond(
+ NexusErrorJson("Could not store the new
account into database")
+ )
+ return@post
+ }
+ call.respondText("Backup restored")
+
+ return@post
}
- logger.info("Restoring keys, creating new user:
$userId")
- try {
+ if (body.get("data") != null) {
+ val data = Gson().fromJson(
+ body.get("data"),
+ EbicsNewTransport::class.java
+ )
+ val pairA = CryptoUtil.generateRsaKeyPair(2048)
+ val pairB = CryptoUtil.generateRsaKeyPair(2048)
+ val pairC = CryptoUtil.generateRsaKeyPair(2048)
transaction {
- EbicsSubscriberEntity.new(body.transport.name)
{
- this.nexusUser = extractNexusUser(userId)
- ebicsURL = body.backup.ebicsURL
- hostID = body.backup.hostID
- partnerID = body.backup.partnerID
- userID = body.backup.userID
- signaturePrivateKey =
SerialBlob(sigKey.encoded)
- encryptionPrivateKey =
SerialBlob(encKey.encoded)
- authenticationPrivateKey =
SerialBlob(authKey.encoded)
+ EbicsSubscriberEntity.new(transport.name) {
+ nexusUser = extractNexusUser(userId)
+ ebicsURL = data.ebicsURL
+ hostID = data.hostID
+ partnerID = data.partnerID
+ userID = data.userID
+ systemID = data.systemID
+ signaturePrivateKey =
SerialBlob(pairA.private.encoded)
+ encryptionPrivateKey =
SerialBlob(pairB.private.encoded)
+ authenticationPrivateKey =
SerialBlob(pairC.private.encoded)
}
}
- } catch (e: Exception) {
- print(e)
- call.respond(
- NexusErrorJson("Could not store the new
account into database")
- )
+ call.respondText("EBICS user successfully created")
return@post
}
- call.respondText("Backup restored")
- return@post
+ throw NexusError(
+ HttpStatusCode.BadRequest,
+ "Neither restore or new transport were specified."
+ )
}
- }
- when (body.data) {
- is EbicsNewTransport -> {
- logger.debug("Creating new transport:
${body.transport.name}")
- val pairA = CryptoUtil.generateRsaKeyPair(2048)
- val pairB = CryptoUtil.generateRsaKeyPair(2048)
- val pairC = CryptoUtil.generateRsaKeyPair(2048)
- transaction {
- EbicsSubscriberEntity.new(body.transport.name) {
- nexusUser = extractNexusUser(userId)
- ebicsURL = body.data.ebicsURL
- hostID = body.data.hostID
- partnerID = body.data.partnerID
- userID = body.data.userID
- systemID = body.data.systemID
- signaturePrivateKey =
SerialBlob(pairA.private.encoded)
- encryptionPrivateKey =
SerialBlob(pairB.private.encoded)
- authenticationPrivateKey =
SerialBlob(pairC.private.encoded)
- }
- }
- call.respondText("EBICS user successfully created")
- return@post
+ else -> {
+ throw NexusError(
+ HttpStatusCode.BadRequest,
+ "Invalid transport type '${transport.type}'"
+ )
}
- } // end of second 'when'.
-
- call.respond(
- HttpStatusCode.BadRequest,
- "Neither backup nor new transport given in request"
- )
- return@post
+ }
}
/**
* Sends to the bank a message "MSG" according to the transport
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index b259bb5..f3dd614 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -226,7 +226,7 @@ class Taler(app: Route) {
val creditorObj = parsePayto(transferRequest.credit_account)
val opaque_row_id = transaction {
val creditorData = parsePayto(transferRequest.credit_account)
- val exchangeBankAccount =
getBankAccountFromNexusUserId(exchangeId)
+ val exchangeBankAccount =
getBankAccountsFromNexusUserId(exchangeId).first()
val nexusUser = extractNexusUser(exchangeId)
/** Checking the UID has the desired characteristics */
TalerRequestedPaymentEntity.find {
@@ -251,9 +251,7 @@ class Taler(app: Route) {
subject = transferRequest.wtid,
sum = amountObj.amount,
currency = amountObj.currency,
- debitorName = exchangeBankAccount.accountHolder,
- debitorBic = exchangeBankAccount.bankCode,
- debitorIban = exchangeBankAccount.iban
+ debitorAccount = exchangeBankAccount.id.value
),
nexusUser
)
@@ -264,11 +262,10 @@ class Taler(app: Route) {
transactionType = "DBIT"
currency = amountObj.currency
this.amount = amountObj.amount.toPlainString()
- debitorName = "Exchange Company"
- debitorIban = exchangeBankAccount.iban
- creditorName = creditorObj.name
- creditorIban = creditorObj.iban
counterpartBic = creditorObj.bic
+ counterpartIban = creditorObj.iban
+ counterpartName = creditorObj.name
+ bankAccount = exchangeBankAccount
bookingDate = DateTime.now().millis
this.nexusUser = nexusUser
status = "BOOK"
@@ -312,21 +309,20 @@ class Taler(app: Route) {
val debtor = parsePayto(addIncomingData.debit_account)
val amount = parseAmount(addIncomingData.amount)
val (bookingDate, opaque_row_id) = transaction {
- val exchangeBankAccount =
getBankAccountFromNexusUserId(exchangeId)
+ val exchangeBankAccount =
getBankAccountsFromNexusUserId(exchangeId).first()
val rawPayment = RawBankTransactionEntity.new {
sourceFileName = "test"
unstructuredRemittanceInformation =
addIncomingData.reserve_pub
transactionType = "CRDT"
currency = amount.currency
this.amount = amount.amount.toPlainString()
- creditorIban = exchangeBankAccount.iban
- creditorName = exchangeBankAccount.accountHolder
- debitorIban = debtor.iban
- debitorName = debtor.name
counterpartBic = debtor.bic
+ counterpartName = debtor.name
+ counterpartIban = debtor.iban
bookingDate = DateTime.now().millis
status = "BOOK"
nexusUser = extractNexusUser(exchangeId)
+ bankAccount = exchangeBankAccount
}
/** This payment is "valid by default" and will be returned
* as soon as the exchange will ask for new payments. */
@@ -355,30 +351,26 @@ class Taler(app: Route) {
* places it into a further table. Eventually, another routine will
perform
* all the prepared payments. */
app.post("/ebics/taler/{id}/accounts/{acctid}/refund-invalid-payments") {
+ val userId =
authenticateRequest(call.request.headers["Authorization"])
+ val nexusUser = getNexusUser(userId)
+ val callerBankAccount = expectNonNull(call.parameters["acctid"])
transaction {
- val nexusUser = extractNexusUser(call.parameters["id"])
- val acctid = expectAcctidTransaction(call.parameters["acctid"])
- if
(!subscriberHasRights(getEbicsSubscriberFromUser(nexusUser), acctid)) {
- throw NexusError(
- HttpStatusCode.Forbidden,
- "The requester can't drive such account (${acctid.id})"
- )
- }
- val requesterBankAccount =
getBankAccountFromNexusUserId(nexusUser.id.value)
+ val bankAccount = getBankAccount(
+ userId,
+ callerBankAccount
+ )
TalerIncomingPaymentEntity.find {
TalerIncomingPayments.refunded eq false and
(TalerIncomingPayments.valid eq false)
}.forEach {
addPreparedPayment(
Pain001Data(
- creditorName = it.payment.debitorName,
- creditorIban = it.payment.debitorIban,
+ creditorName = it.payment.counterpartName,
+ creditorIban = it.payment.counterpartIban,
creditorBic = it.payment.counterpartBic,
sum = calculateRefund(it.payment.amount),
subject = "Taler refund",
- debitorIban = requesterBankAccount.iban,
- debitorBic = requesterBankAccount.bankCode,
- debitorName = requesterBankAccount.accountHolder,
- currency = it.payment.currency
+ currency = it.payment.currency,
+ debitorAccount = callerBankAccount
),
nexusUser
)
@@ -398,18 +390,22 @@ class Taler(app: Route) {
val id = ensureNonNull(call.parameters["id"])
// first find highest ID value of already processed rows.
transaction {
- val subscriberAccount = getBankAccountFromNexusUserId(id)
+ val subscriberAccount =
getBankAccountsFromNexusUserId(id).first()
/**
* Search for fresh incoming payments in the raw table, and
making pointers
- * from the Taler incoming payments table to the found fresh
payments.
+ * from the Taler incoming payments table to the found fresh
(and valid!) payments.
*/
val latestIncomingPaymentId: Long =
TalerIncomingPaymentEntity.getLast()
RawBankTransactionEntity.find {
- /** select payments having the exchange as the credited
party */
- RawBankTransactionsTable.creditorIban eq
subscriberAccount.iban and
+ /** Those with exchange bank account involved */
+ RawBankTransactionsTable.bankAccount eq
subscriberAccount.id.value and
+ /** Those that are incoming */
+ (RawBankTransactionsTable.transactionType eq
"CRDT") and
+ /** Those that are booked */
(RawBankTransactionsTable.status eq "BOOK") and
- /** avoid processing old payments from the raw
table */
+ /** Those that came later than the latest
processed payment */
(RawBankTransactionsTable.id.greater(latestIncomingPaymentId))
+
}.forEach {
if (duplicatePayment(it)) {
logger.warn("Incomint payment already seen")
@@ -437,8 +433,12 @@ class Taler(app: Route) {
*/
val latestOutgoingPaymentId =
TalerRequestedPaymentEntity.getLast()
RawBankTransactionEntity.find {
+ /** Those that came after the last processed payment */
RawBankTransactionsTable.id greater
latestOutgoingPaymentId and
- ( RawBankTransactionsTable.debitorIban eq
subscriberAccount.iban)
+ /** Those involving the exchange bank account */
+ (RawBankTransactionsTable.bankAccount eq
subscriberAccount.id.value) and
+ /** Those that are outgoing */
+ (RawBankTransactionsTable.transactionType eq
"DBIT")
}.forEach {
if (paymentFailed(it)) {
logger.error("Bank didn't accept one payment from the
exchange")
@@ -485,7 +485,7 @@ class Taler(app: Route) {
val history = TalerOutgoingHistory()
transaction {
/** Retrieve all the outgoing payments from the _clean Taler
outgoing table_ */
- val subscriberBankAccount =
getBankAccountFromNexusUserId(subscriberId)
+ val subscriberBankAccount =
getBankAccountsFromNexusUserId(subscriberId).first()
val reqPayments = TalerRequestedPaymentEntity.find {
TalerRequestedPayments.rawConfirmed.isNotNull() and
startCmpOp
}.orderTaler(delta)
@@ -539,12 +539,12 @@ class Taler(app: Route) {
val nexusUser = extractNexusUser(exchangeId)
BankAccountMapEntity.new {
bankAccount = newBankAccount
- ebicsSubscriber =
getEbicsSubscriberFromUser(nexusUser)
+ ebicsSubscriber = getEbicsTransport(exchangeId)
this.nexusUser = nexusUser
}
}
}
- val exchangeBankAccount =
getBankAccountFromNexusUserId(exchangeId)
+ val exchangeBankAccount =
getBankAccountsFromNexusUserId(exchangeId).first()
val orderedPayments = TalerIncomingPaymentEntity.find {
TalerIncomingPayments.valid eq true and startCmpOp
}.orderTaler(delta)
@@ -556,11 +556,15 @@ class Taler(app: Route) {
row_id = it.id.value,
amount =
"${it.payment.currency}:${it.payment.amount}",
reserve_pub =
it.payment.unstructuredRemittanceInformation,
- debit_account = buildPaytoUri(
- it.payment.debitorName,
it.payment.debitorIban, it.payment.counterpartBic
- ),
credit_account = buildPaytoUri(
- it.payment.creditorName,
it.payment.creditorIban, exchangeBankAccount.bankCode
+ it.payment.bankAccount.accountHolder,
+ it.payment.bankAccount.iban,
+ it.payment.bankAccount.bankCode
+ ),
+ debit_account = buildPaytoUri(
+ it.payment.counterpartName,
+ it.payment.counterpartIban,
+ it.payment.counterpartBic
)
)
)
diff --git a/nexus/src/test/kotlin/PainGeneration.kt
b/nexus/src/test/kotlin/PainGeneration.kt
index e257c50..82b1470 100644
--- a/nexus/src/test/kotlin/PainGeneration.kt
+++ b/nexus/src/test/kotlin/PainGeneration.kt
@@ -31,9 +31,7 @@ class PainTest {
creditorBic = "CREDIT BIC"
creditorName = "CREDIT NAME"
paymentId = 1
- msgId = 1
endToEndId = 1
- date = DateTime.now().millis
nexusUser = NexusUserEntity.new(id = "mock") { }
}
}
diff --git a/nexus/src/test/kotlin/taler.kt b/nexus/src/test/kotlin/taler.kt
index d582a97..cd7c327 100644
--- a/nexus/src/test/kotlin/taler.kt
+++ b/nexus/src/test/kotlin/taler.kt
@@ -2,15 +2,13 @@ package tech.libeufin.nexus
import io.ktor.routing.RootRouteSelector
import io.ktor.routing.Route
-import io.ktor.routing.RouteSelector
-import io.ktor.routing.RouteSelectorEvaluation
import io.ktor.util.InternalAPI
-import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
-import tech.libeufin.nexus.Taler
import tech.libeufin.util.Amount
import java.math.BigDecimal
+/*
class TalerTest {
@InternalAPI
@@ -35,4 +33,6 @@ class TalerTest {
val amount25 = taler.parseAmount("EUR:2.5")
assert(amount25.amount.compareTo(Amount("2.5")) == 0)
}
-}
\ No newline at end of file
+}
+
+ */
\ No newline at end of file
diff --git a/util/src/main/kotlin/ParametersChecks.kt
b/util/src/main/kotlin/ParametersChecks.kt
index cc910b4..abf5bc2 100644
--- a/util/src/main/kotlin/ParametersChecks.kt
+++ b/util/src/main/kotlin/ParametersChecks.kt
@@ -11,6 +11,13 @@ fun expectInt(param: String): Int {
}
}
+fun <T>expectNonNull(param: T?): T {
+ return param ?: throw UtilError(
+ HttpStatusCode.BadRequest,
+ "Non-null value expected."
+ )
+}
+
fun expectLong(param: String): Long {
return try {
param.toLong()
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [libeufin] branch master updated (9799d88 -> 8f11898),
gnunet <=