libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 1bb13f2318f89312542d5cfa723e4049d7afde3e
parent fd6b16355c3c14111a0c23688ee0c6806e51c3a7
Author: Antoine A <>
Date:   Thu,  6 Feb 2025 10:25:15 +0100

libeufin-bank: always use legal name in cashout payto

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt | 19++++++++++---------
Mbank/src/test/kotlin/CoreBankApiTest.kt | 9++++-----
Mcommon/src/main/kotlin/TalerCommon.kt | 8+++++---
Mcommon/src/main/kotlin/db/types.kt | 8+++++++-
Mcommon/src/test/kotlin/PaytoTest.kt | 6+++---
5 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt @@ -75,7 +75,7 @@ class AccountDAO(private val db: Database) { setString(1, name) setString(2, email) setString(3, phone) - setString(4, cashoutPayto?.full(name)) + setString(4, cashoutPayto?.simple()) setString(5, tanChannel?.name) setBoolean(6, checkPaytoIdempotent) setString(7, internalPayto.canonical) @@ -138,7 +138,7 @@ class AccountDAO(private val db: Database) { setString(3, name) setString(4, email) setString(5, phone) - setString(6, cashoutPayto?.full(name)) + setString(6, cashoutPayto?.simple()) setString(7, tanChannel?.name) one { it.getLong("customer_id") } } @@ -295,7 +295,7 @@ class AccountDAO(private val db: Database) { phone = it.getString("phone"), email = it.getString("email"), name = it.getString("name"), - cashoutPayTo = it.getString("cashout_payto"), + cashoutPayTo = it.getOptIbanPayto("cashout_payto")?.simple(), debtLimit = it.getAmount("max_debt", db.bankCurrency), minCashout = it.getOptAmount("min_cashout", db.bankCurrency), ) @@ -318,13 +318,13 @@ class AccountDAO(private val db: Database) { TanChannel.email -> curr.email null -> null } - // Cashout payto with a receiver-name using if receiver-name is missing the new named if present or the current one - val fullCashoutPayto = cashoutPayto.get()?.full(name ?: curr.name) + // Cashout payto without a receiver-name + val simpleCashoutPayto = cashoutPayto.get()?.simple() // Check reconfig rights if (checkName && name != curr.name) return@serializableTransaction AccountPatchResult.NonAdminName - if (checkCashout && fullCashoutPayto != curr.cashoutPayTo) + if (checkCashout && simpleCashoutPayto != curr.cashoutPayTo) return@serializableTransaction AccountPatchResult.NonAdminCashout if (checkDebtLimit && debtLimit != curr.debtLimit) return@serializableTransaction AccountPatchResult.NonAdminDebtLimit @@ -394,7 +394,7 @@ class AccountDAO(private val db: Database) { }, "WHERE customer_id = ?", sequence { - cashoutPayto.some { yield(fullCashoutPayto) } + cashoutPayto.some { yield(simpleCashoutPayto) } phone.some { yield(it) } email.some { yield(it) } tan_channel.some { yield(it?.name) } @@ -561,14 +561,15 @@ class AccountDAO(private val db: Database) { ) { setString(1, username) oneOrNull { + val name = it.getString("name") AccountData( - name = it.getString("name"), + name = name, contact_data = ChallengeContactData( email = Option.Some(it.getString("email")), phone = Option.Some(it.getString("phone")) ), tan_channel = it.getOptEnum<TanChannel>("tan_channel"), - cashout_payto_uri = it.getString("cashout_payto"), + cashout_payto_uri = it.getOptIbanPayto("cashout_payto")?.full(name), payto_uri = it.getBankPayto("internal_payto", "name", db.ctx), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -551,17 +551,16 @@ class CoreBankAccountsApiTest { client.getA("/accounts/cashout_guess").assertOkJson<AccountData> { assertEquals(payto.full("Mr Guess My Name"), it.cashout_payto_uri) } - val full = payto.full("Santa Claus") client.post("/accounts") { json { "username" to "cashout_keep" "password" to "cashout_keep-password" "name" to "Mr Keep My Name" - "cashout_payto_uri" to full + "cashout_payto_uri" to payto.full("Santa Claus") } }.assertOk() client.getA("/accounts/cashout_keep").assertOkJson<AccountData> { - assertEquals(full, it.cashout_payto_uri) + assertEquals(payto.full("Mr Keep My Name"), it.cashout_payto_uri) } // Check input restrictions @@ -906,8 +905,8 @@ class CoreBankAccountsApiTest { for ((cashout, name, expect) in listOf( Triple(cashout.canonical, null, canonical.full("Mr Cashout Cashout")), Triple(cashout.canonical, "New name", canonical.full("New name")), - Triple(cashout.full("Full name"), null, cashout.full("Full name")), - Triple(cashout.full("Full second name"), "Another name", cashout.full("Full second name")) + Triple(cashout.full("Full name"), null, cashout.full("New name")), + Triple(cashout.full("Full second name"), "Another name", cashout.full("Another name")) )) { client.patchAdmin("/accounts/cashout") { json { diff --git a/common/src/main/kotlin/TalerCommon.kt b/common/src/main/kotlin/TalerCommon.kt @@ -412,11 +412,13 @@ class IbanPayto internal constructor( val bic: String?, val iban: IBAN ): Payto() { - override fun toString(): String = parsed.toString() - /** Transform an IBAN payto URI to its full form, using [defaultName] if receiver-name is missing */ - fun full(defaultName: String): String = build(iban.toString(), bic, receiverName ?: defaultName) + /** Transform an IBAN payto URI to its simple form without any query */ + fun simple(): String = build(iban.toString(), bic, null) + + /** Transform an IBAN payto URI to its full form, using [name] as its receiver-name */ + fun full(name: String): String = build(iban.toString(), bic, name) internal object Serializer : KSerializer<IbanPayto> { override val descriptor: SerialDescriptor = diff --git a/common/src/main/kotlin/db/types.kt b/common/src/main/kotlin/db/types.kt @@ -1,6 +1,6 @@ /* * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. + * Copyright (C) 2024-2025 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 @@ -61,6 +61,12 @@ fun ResultSet.getBankPayto(payto: String, name: String?, ctx: BankPaytoCtx): Str , ctx) } +fun ResultSet.getOptIbanPayto(payto: String): IbanPayto? { + val raw = getString(payto) + if (raw == null) return null + return Payto.parse(raw).expectIban() +} + fun ResultSet.getIbanPayto(payto: String): IbanPayto { return Payto.parse(getString(payto)).expectIban() } \ No newline at end of file diff --git a/common/src/test/kotlin/PaytoTest.kt b/common/src/test/kotlin/PaytoTest.kt @@ -1,6 +1,6 @@ /* * This file is part of LibEuFin. - * Copyright (C) 2024 Taler Systems S.A. + * Copyright (C) 2024-2025 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 @@ -68,8 +68,8 @@ class PaytoTest { "NotGiven", "Grothoff Hans", null ) val full = listOf( - "payto://iban/BIC/CH9300762011623852957?receiver-name=NotGiven", - "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans", + "payto://iban/BIC/CH9300762011623852957?receiver-name=Santa", + "payto://iban/CH9300762011623852957?receiver-name=Santa", "payto://iban/CH9300762011623852957?receiver-name=Santa", ) for ((i, input) in inputs.withIndex()) {