diff options
author | Florian Dold <florian@dold.me> | 2021-08-07 16:10:25 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2021-08-07 16:10:35 +0200 |
commit | 05ddacd80641db9ebd00ba6bb20aa8200c8b76f8 (patch) | |
tree | f6830f6cb04ea55f127744ee29d2ef524216190d | |
parent | 695c23c2b1a9ee05409fff3d74621393edce042b (diff) | |
download | libeufin-05ddacd80641db9ebd00ba6bb20aa8200c8b76f8.tar.gz libeufin-05ddacd80641db9ebd00ba6bb20aa8200c8b76f8.tar.bz2 libeufin-05ddacd80641db9ebd00ba6bb20aa8200c8b76f8.zip |
check amount, catch exceptions when refunding
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 3 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt | 25 | ||||
-rw-r--r-- | nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt | 1 | ||||
-rw-r--r-- | sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 17 | ||||
-rw-r--r-- | util/src/main/kotlin/amounts.kt | 28 |
6 files changed, 68 insertions, 12 deletions
diff --git a/debian/changelog b/debian/changelog index 6cddc2e1..7666d599 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libeufin (0.0.1-9) unstable; urgency=medium + + * Various bugfixes. + + -- Florian Dold <florian@dold.me> Sat, 07 Aug 2021 16:09:59 +0200 + libeufin (0.0.1-8) unstable; urgency=medium * Various bugfixes. diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt index 75c5f880..8919024a 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt @@ -69,6 +69,9 @@ class TalerInvalidIncomingPaymentEntity(id: EntityID<Long>) : LongEntity(id) { var payment by NexusBankTransactionEntity referencedOn TalerInvalidIncomingPaymentsTable.payment var timestampMs by TalerInvalidIncomingPaymentsTable.timestampMs + // FIXME: This should probably not be called refunded, and + // we should have a foreign key to the payment that sends the + // money back. var refunded by TalerInvalidIncomingPaymentsTable.refunded } diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt index 33f09651..33403da2 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Taler.kt @@ -43,7 +43,9 @@ import tech.libeufin.util.* import kotlin.math.abs import kotlin.math.min -/** Payment initiating data structures: one endpoint "$BASE_URL/transfer". */ +/** + * Request body for "$TWG_BASE_URL/transfer". + */ data class TalerTransferRequest( val request_uid: String, val amount: String, @@ -94,7 +96,9 @@ data class GnunetTimestamp( val t_ms: Long ) -/** Sort query results in descending order for negative deltas, and ascending otherwise. */ +/** + * Sort query results in descending order for negative deltas, and ascending otherwise. + */ fun <T : Entity<Long>> SizedIterable<T>.orderTaler(delta: Int): List<T> { return if (delta < 0) { this.sortedByDescending { it.id } @@ -165,7 +169,7 @@ fun customConverter(body: Any): String { fun extractReservePubFromSubject(rawSubject: String): String? { val re = "\\b[a-z0-9A-Z]{52}\\b".toRegex() val result = re.find(rawSubject.replace("[\n]+".toRegex(), "")) ?: return null - return result.value.toUpperCase() + return result.value.uppercase() } private fun getTalerFacadeState(fcid: String): TalerFacadeStateEntity { @@ -185,7 +189,7 @@ private fun getTalerFacadeBankAccount(fcid: String): NexusBankAccountEntity { val facadeState = getTalerFacadeState(fcid) return NexusBankAccountEntity.findByName(facadeState.bankAccount) ?: throw NexusError( HttpStatusCode.NotFound, - "The facade: ${fcid} doesn't manage bank account: ${facadeState.bankAccount}" + "The facade: $fcid doesn't manage bank account: ${facadeState.bankAccount}" ) } @@ -356,7 +360,7 @@ fun maybePrepareRefunds(bankAccount: NexusBankAccountEntity, lastSeenId: Long) { throw NexusError(HttpStatusCode.InternalServerError, "Unexpected void payment, cannot refund") } val debtorAccount = paymentData.batches[0].batchTransactions[0].details.debtorAccount - if (debtorAccount == null || debtorAccount.iban == null) { + if (debtorAccount?.iban == null) { logger.error("Could not find a IBAN to refund in transaction (AcctSvcrRef): ${paymentData.accountServicerRef}, aborting refund") throw NexusError(HttpStatusCode.InternalServerError, "IBAN to refund not found") } @@ -441,7 +445,12 @@ fun ingestTalerTransactions(bankAccountId: String) { } lastId = it.id.value } - maybePrepareRefunds(bankAccount, facadeState.highestSeenMessageSerialId) + try { + // FIXME: This currently does not do proper error handing. + maybePrepareRefunds(bankAccount, facadeState.highestSeenMessageSerialId) + } catch (e: Exception) { + logger.warn("sending refund payment failed", e); + } facadeState.highestSeenMessageSerialId = lastId } @@ -561,8 +570,8 @@ fun talerFacadeRoutes(route: Route, httpClient: HttpClient) { route.get("/config") { val facadeId = ensureNonNull(call.parameters["fcid"]) call.request.requirePermission( - PermissionQuery("facade", facadeId, "facade.talerWireGateway.transfer"), - PermissionQuery("facade", facadeId, "facade.talerWireGateway.history") + PermissionQuery("facade", facadeId, "facade.talerwiregateway.transfer"), + PermissionQuery("facade", facadeId, "facade.talerwiregateway.history") ) call.respond(object { val version = "0.0.0" diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt index 3c20fbf1..4742d99b 100644 --- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt +++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt @@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import execThrowableOrTerminate import io.ktor.application.* import io.ktor.client.* import io.ktor.features.* diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt index 08a11535..9201fa38 100644 --- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt +++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -89,6 +89,7 @@ import tech.libeufin.sandbox.BankAccountTransactionsTable.pmtInfId import tech.libeufin.util.* import tech.libeufin.util.ebics_h004.EbicsResponse import tech.libeufin.util.ebics_h004.EbicsTypes +import validatePlainAmount import java.net.BindException import java.util.* import kotlin.random.Random @@ -107,15 +108,16 @@ class Config : CliktCommand("Insert one configuration into the database") { helpFormatter = CliktHelpFormatter(showDefaultValues = true) } } + private val hostnameOption by argument( - "HOSTNAME", help="hostname that serves this configuration" + "HOSTNAME", help = "hostname that serves this configuration" ) private val currencyOption by option("--currency").default("EUR") private val bankDebtLimitOption by option("--bank-debt-limit").int().default(1000000) private val usersDebtLimitOption by option("--users-debt-limit").int().default(1000) private val allowRegistrationsOption by option( "--allow-registrations", - help="(default: true)" /* mentioning here as help message did not. */ + help = "(default: true)" /* mentioning here as help message did not. */ ).flag(default = true) override fun run() { @@ -141,6 +143,7 @@ class ResetTables : CliktCommand("Drop all the tables from the database") { helpFormatter = CliktHelpFormatter(showDefaultValues = true) } } + override fun run() { val dbConnString = getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME) execThrowableOrTerminate { @@ -223,6 +226,7 @@ class SandboxCommand : CliktCommand(invokeWithoutSubcommand = true, printHelpOnE init { versionOption(getVersion()) } + override fun run() = Unit } @@ -369,7 +373,7 @@ fun serverMain(dbName: String, port: Int) { transaction { // check if username is taken. - var maybeUser = SandboxUserEntity.find { + val maybeUser = SandboxUserEntity.find { SandboxUsersTable.username eq username }.firstOrNull() // Will be converted to a HTML response. @@ -434,6 +438,7 @@ fun serverMain(dbName: String, port: Int) { val version = "0.0.0-dev.0" }) } + // only reason for a post is to hide the iban (to some degree.) post("/admin/payments/camt") { val body = call.receiveJson<CamtParams>() @@ -448,6 +453,12 @@ fun serverMain(dbName: String, port: Int) { val body = call.receiveJson<IncomingPaymentInfo>() // FIXME: generate nicer UUID! val accountLabel = ensureNonNull(call.parameters["label"]) + if (!validatePlainAmount(body.amount)) { + throw SandboxError( + HttpStatusCode.BadRequest, + "invalid amount (should be plain amount without currency)" + ) + } transaction { val account = getBankAccountFromLabel(accountLabel) val randId = getRandomString(16) diff --git a/util/src/main/kotlin/amounts.kt b/util/src/main/kotlin/amounts.kt new file mode 100644 index 00000000..04543f81 --- /dev/null +++ b/util/src/main/kotlin/amounts.kt @@ -0,0 +1,28 @@ +import io.ktor.http.* +import tech.libeufin.util.AmountWithCurrency +import tech.libeufin.util.EbicsProtocolError + +/* + * This file is part of LibEuFin. + * Copyright (C) 2021 Taler Systems S.A. + * + * LibEuFin is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3, or + * (at your option) any later version. + * + * LibEuFin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with LibEuFin; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/> + */ + +val re = Regex("^([0-9]+(\\.[0-9]+)?)$") + +fun validatePlainAmount(plainAmount: String): Boolean { + return re.matches(plainAmount) +} |