libeufin

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

commit 54ff928887a5b5a96a262f35bf9e45e646184e07
parent 836956edb700e953ceb03fbb862822c4f31fe722
Author: Antoine A <>
Date:   Mon,  5 Feb 2024 12:14:49 +0100

Fix admin account create with x-taler-bank and improve config error msg

Diffstat:
Mbank/conf/test_x_taler_bank.conf | 2+-
Mbank/src/main/kotlin/tech/libeufin/bank/Config.kt | 22+++++++++-------------
Mbank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 2--
Mbank/src/main/kotlin/tech/libeufin/bank/Main.kt | 2+-
Mbank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 13+++++++++----
Mbank/src/test/kotlin/DatabaseTest.kt | 4++--
Mbank/src/test/kotlin/helpers.kt | 2+-
Mcommon/src/main/kotlin/TalerConfig.kt | 19+++++++++----------
Mcontrib/bank.conf | 6+++---
9 files changed, 35 insertions(+), 37 deletions(-)

diff --git a/bank/conf/test_x_taler_bank.conf b/bank/conf/test_x_taler_bank.conf @@ -5,7 +5,7 @@ ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_NAME = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes -PAYMENT_METHOD = x-taler-bank +WIRE_TYPE = x-taler-bank X_TALER_BANK_PAYTO_HOSTNAME = bank.hostname.test [libeufin-bankdb-postgres] diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt @@ -86,7 +86,7 @@ fun TalerConfig.loadServerConfig(): ServerConfig { return when (val method = requireString("libeufin-bank", "serve")) { "tcp" -> ServerConfig.Tcp(requireNumber("libeufin-bank", "port")) "unix" -> ServerConfig.Unix(requireString("libeufin-bank", "unixpath"), requireNumber("libeufin-bank", "unixpath_mode")) - else -> throw Exception("Unknown server method '$method' expected 'tcp' or 'unix'") + else -> throw Exception(" Unknown server method '$method' expected 'tcp' or 'unix' got '$method'") } } @@ -106,10 +106,10 @@ fun TalerConfig.loadBankConfig(): BankConfig { } } } - val method = when (val raw = lookupString("libeufin-bank", "payment_method")) { + val method = when (val raw = lookupString("libeufin-bank", "wire_type")) { "iban" -> WireMethod.IBAN "x-taler-bank" -> WireMethod.X_TALER_BANK - else -> throw TalerConfigError("expected wire method for section libeufin-bank, option payment_method, but $raw is unknown") + else -> throw TalerConfigError("expected a payment target type for section libeufin-bank, option wire_type, but $raw is unknown") } val payto = when (method) { WireMethod.IBAN -> BankPaytoCtx(bic = lookupString("libeufin-bank", "iban_payto_bic")) @@ -158,39 +158,35 @@ private fun TalerConfig.amount(section: String, option: String, currency: String val amount = try { TalerAmount(amountStr) } catch (e: Exception) { - throw TalerConfigError("expected amount for section $section, option $option, but amount is malformed") + throw TalerConfigError("amount", section, option, "but amount is malformed") } if (amount.currency != currency) { - throw TalerConfigError( - "expected amount for section $section, option $option, but currency is wrong (got ${amount.currency} expected $currency" - ) + throw TalerConfigError("amount", section, option, "but currency is wrong : got ${amount.currency} expected $currency") } return amount } private fun TalerConfig.requireAmount(section: String, option: String, currency: String): TalerAmount = - amount(section, option, currency) ?: - throw TalerConfigError("expected amount for section $section, option $option, but config value is empty") + amount(section, option, currency) ?: throw TalerConfigError("amount", section, option, "but config value is empty") private fun TalerConfig.decimalNumber(section: String, option: String): DecimalNumber? { val numberStr = lookupString(section, option) ?: return null try { return DecimalNumber(numberStr) } catch (e: Exception) { - throw TalerConfigError("expected decimal number for section $section, option $option, but number is malformed") + throw TalerConfigError("decimal number", section, option, "but number is malformed") } } private fun TalerConfig.requireDecimalNumber(section: String, option: String): DecimalNumber - = decimalNumber(section, option) ?: - throw TalerConfigError("expected decimal number for section $section, option $option, but config value is empty") + = decimalNumber(section, option) ?: throw TalerConfigError("decimal number", section, option, "but config value is empty") private fun TalerConfig.RoundingMode(section: String, option: String): RoundingMode? { val str = lookupString(section, option) ?: return null; try { return RoundingMode.valueOf(str) } catch (e: Exception) { - throw TalerConfigError("expected rouding mode for section $section, option $option, but $str is unknown") + throw TalerConfigError("rouding mode", section, option, "but $str is unknown") } } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -236,8 +236,6 @@ suspend fun createAccount( return Pair(res, internalPayto.bank(req.name, cfg.payto)) } } - - } suspend fun patchAccount( diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -238,7 +238,7 @@ class BankDbInit : CliktCommand("Initialize the libeufin-bank database", name = initializeDatabaseTables(conn, cfg, sqlFilePrefix = "libeufin-bank") } // Create admin account if missing - val res = maybeCreateAdminAccount(db, ctx) // logs provided by the helper + val res = createAdminAccount(db, ctx) // logs provided by the helper when (res) { AccountCreationResult.BonusBalanceInsufficient -> {} AccountCreationResult.LoginReuse -> {} diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -110,7 +110,7 @@ fun ApplicationCall.longParameter(name: String): Long { * * It returns false in case of problems, true otherwise. */ -suspend fun maybeCreateAdminAccount(db: Database, ctx: BankConfig, pw: String? = null): AccountCreationResult { +suspend fun createAdminAccount(db: Database, cfg: BankConfig, pw: String? = null): AccountCreationResult { var pwStr = pw; if (pwStr == null) { val pwBuf = ByteArray(32) @@ -118,15 +118,20 @@ suspend fun maybeCreateAdminAccount(db: Database, ctx: BankConfig, pw: String? = pwStr = String(pwBuf, Charsets.UTF_8) } + val payto = when (cfg.wireMethod) { + WireMethod.IBAN -> IbanPayto.rand() + WireMethod.X_TALER_BANK -> XTalerBankPayto.forUsername("admin") + } + return db.account.create( login = "admin", password = pwStr, name = "Bank administrator", - internalPayto = IbanPayto.rand(), + internalPayto = payto, isPublic = false, isTalerExchange = false, - maxDebt = ctx.defaultDebtLimit, - bonus = TalerAmount(0, 0, ctx.regionalCurrency), + maxDebt = cfg.defaultDebtLimit, + bonus = TalerAmount(0, 0, cfg.regionalCurrency), checkPaytoIdempotent = false, email = null, phone = null, diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt @@ -38,9 +38,9 @@ class DatabaseTest { @Test fun createAdmin() = setup { db, ctx -> // Create admin account - assertEquals(AccountCreationResult.Success, maybeCreateAdminAccount(db, ctx)) + assertEquals(AccountCreationResult.Success, createAdminAccount(db, ctx)) // Checking idempotency - assertEquals(AccountCreationResult.LoginReuse, maybeCreateAdminAccount(db, ctx)) + assertEquals(AccountCreationResult.LoginReuse, createAdminAccount(db, ctx)) } @Test diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt @@ -128,7 +128,7 @@ fun bankSetup( tanChannel = null )) // Create admin account - assertEquals(AccountCreationResult.Success, maybeCreateAdminAccount(db, ctx, "admin-password")) + assertEquals(AccountCreationResult.Success, createAdminAccount(db, ctx, "admin-password")) testApplication { application { corebankWebApp(db, ctx) diff --git a/common/src/main/kotlin/TalerConfig.kt b/common/src/main/kotlin/TalerConfig.kt @@ -36,7 +36,10 @@ private val reSection = Regex("^\\s*\\[\\s*([^]]*)\\s*]\\s*$") private val reParam = Regex("^\\s*([^=]+?)\\s*=\\s*(.*?)\\s*$") private val reDirective = Regex("^\\s*@([a-zA-Z-_]+)@\\s*(.*?)\\s*$") -class TalerConfigError(m: String) : Exception(m) +class TalerConfigError(m: String) : Exception(m) { + constructor(type: String, section: String, option: String, err: String): this("expected $type in configuration section $section option $option $err") + constructor(type: String, section: String, option: String): this("expected $type in configuration section $section option $option") +} /** * Information about how the configuration is loaded. @@ -423,25 +426,22 @@ class TalerConfig internal constructor( } fun requireString(section: String, option: String): String = - lookupString(section, option) ?: - throw TalerConfigError("expected string in configuration section $section option $option") + lookupString(section, option) ?: throw TalerConfigError("string", section, option) fun requireNumber(section: String, option: String): Int = - lookupString(section, option)?.toInt() ?: - throw TalerConfigError("expected number in configuration section $section option $option") + lookupString(section, option)?.toInt() ?: throw TalerConfigError("number", section, option) fun lookupBoolean(section: String, option: String): Boolean? { val entry = lookupString(section, option) ?: return null return when (val v = entry.lowercase()) { "yes" -> true "no" -> false - else -> throw TalerConfigError("expected yes/no in configuration section $section option $option but got $v") + else -> throw TalerConfigError("yes/no", section, option, "but got '$v'") } } fun requireBoolean(section: String, option: String): Boolean = - lookupBoolean(section, option) ?: - throw TalerConfigError("expected boolean in configuration section $section option $option") + lookupBoolean(section, option) ?: throw TalerConfigError("boolean", section, option) fun lookupPath(section: String, option: String): Path? { val entry = lookupString(section, option) ?: return null @@ -449,6 +449,5 @@ class TalerConfig internal constructor( } fun requirePath(section: String, option: String): Path = - lookupPath(section, option) ?: - throw TalerConfigError("expected path for section $section option $option") + lookupPath(section, option) ?: throw TalerConfigError("path", section, option) } diff --git a/contrib/bank.conf b/contrib/bank.conf @@ -3,14 +3,14 @@ # Internal currency of the libeufin-bank CURRENCY = KUDOS -# Supported payment method, this can either be iban or x-taler-bank -PAYMENT_METHOD = iban +# Supported payment target type, this can either be iban or x-taler-bank +WIRE_TYPE = iban # Bank BIC used in generated iban payto URI IBAN_PAYTO_BIC = SANDBOXX # Bank hostname used in generated x-taler-bank payto URI -# X_TALER_BANK_PAYTO_HOSTNAME=bank.$FOO.taler.net +# X_TALER_BANK_PAYTO_HOSTNAME = bank.$FOO.taler.net # Default debt limit for newly created accounts Default is CURRENCY:0 # DEFAULT_DEBT_LIMIT = KUDOS:200