libeufin

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

commit ce965db8e9f593e460be493e882eafd655cc1257
parent 9ff6e5a57b13668c555b75488704b15abc052166
Author: Antoine A <>
Date:   Tue, 28 Nov 2023 15:35:39 +0000

Add CLI command to create account

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 2+-
Mbank/src/main/kotlin/tech/libeufin/bank/Main.kt | 73++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mintegration/test/IntegrationTest.kt | 29++++++++++-------------------
3 files changed, 73 insertions(+), 31 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -169,7 +169,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { TalerErrorCode.BANK_UNALLOWED_DEBIT ) AccountCreationResult.LoginReuse -> throw conflict( - "Customer username reuse '${req.username}'", + "Account username reuse '${req.username}'", TalerErrorCode.BANK_REGISTER_USERNAME_REUSE ) AccountCreationResult.PayToReuse -> throw conflict( diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -22,10 +22,8 @@ package tech.libeufin.bank import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.options.flag -import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.options.versionOption +import com.github.ajalt.clikt.parameters.arguments.* +import com.github.ajalt.clikt.parameters.options.* import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.http.content.* @@ -323,14 +321,12 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve") } } - - class ChangePw : CliktCommand("Change account password", name = "passwd") { private val configFile by option( "--config", "-c", help = "set the configuration file" ) - private val account by argument("account") + private val username by argument("username") private val password by argument("password") override fun run() { @@ -339,15 +335,70 @@ class ChangePw : CliktCommand("Change account password", name = "passwd") { val dbCfg = cfg.loadDbConfig() val db = Database(dbCfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency) runBlocking { - val res = db.account.reconfigPassword(account, password, null) + val res = db.account.reconfigPassword(username, password, null) when (res) { AccountPatchAuthResult.UnknownAccount -> { - logger.error("password change for '$account' account failed: unknown account") + logger.error("Password change for '$username' account failed: unknown account") exitProcess(1) } AccountPatchAuthResult.OldPasswordMismatch -> { /* Can never happen */ } AccountPatchAuthResult.Success -> { - logger.info("password change for '$account' account succeeded") + logger.info("Password change for '$username' account succeeded") + } + } + } + } +} + +class CreateAccount : CliktCommand("Create an account", name = "create-account") { + private val configFile by option( + "--config", "-c", + help = "set the configuration file" + ) + private val json: RegisterAccountRequest by argument().convert { Json.decodeFromString<RegisterAccountRequest>(it) } + + override fun run() { + val cfg = talerConfig(configFile) + val ctx = cfg.loadBankConfig() + val dbCfg = cfg.loadDbConfig() + val db = Database(dbCfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency) + runBlocking { + if (reservedAccounts.contains(json.username)) { + logger.error("Username '${json.username}' is reserved") + exitProcess(1) + } + + val internalPayto = json.internal_payto_uri ?: IbanPayTo(genIbanPaytoUri()) + val result = db.account.create( + login = json.username, + name = json.name, + email = json.challenge_contact_data?.email, + phone = json.challenge_contact_data?.phone, + cashoutPayto = json.cashout_payto_uri, + password = json.password, + internalPaytoUri = internalPayto, + isPublic = json.is_public, + isTalerExchange = json.is_taler_exchange, + maxDebt = ctx.defaultCustomerDebtLimit, + bonus = if (!json.is_taler_exchange) ctx.registrationBonus + else TalerAmount(0, 0, ctx.regionalCurrency) + ) + + when (result) { + AccountCreationResult.BonusBalanceInsufficient -> { + logger.error("Insufficient admin funds to grant bonus") + exitProcess(1) + } + AccountCreationResult.LoginReuse -> { + logger.error("Account username reuse '${json.username}'") + exitProcess(1) + } + AccountCreationResult.PayToReuse -> { + logger.error("Bank internalPayToUri reuse '${internalPayto.canonical}'") + exitProcess(1) + } + AccountCreationResult.Success -> { + logger.info("Account '${json.username}' created") } } } @@ -357,7 +408,7 @@ class ChangePw : CliktCommand("Change account password", name = "passwd") { class LibeufinBankCommand : CliktCommand() { init { versionOption(getVersion()) - subcommands(ServeBank(), BankDbInit(), ChangePw(), CliConfigCmd(BANK_CONFIG_SOURCE)) + subcommands(ServeBank(), BankDbInit(), CreateAccount(), ChangePw(), CliConfigCmd(BANK_CONFIG_SOURCE)) } override fun run() = Unit diff --git a/integration/test/IntegrationTest.kt b/integration/test/IntegrationTest.kt @@ -19,7 +19,6 @@ import org.junit.Test import tech.libeufin.bank.* -import tech.libeufin.bank.Database as BankDb import tech.libeufin.bank.TalerAmount as BankAmount import tech.libeufin.nexus.* import tech.libeufin.nexus.Database as NexusDb @@ -65,7 +64,16 @@ class IntegrationTest { val bankCmd = LibeufinBankCommand(); bankCmd.run("dbinit -c ../bank/conf/test.conf -r") bankCmd.run("passwd admin password -c ../bank/conf/test.conf") - + val json = obj { + "username" to "exchange" + "password" to "password" + "name" to "Mr Money" + "is_taler_exchange" to true + } + bankCmd.run("create-account '$json' -c ../bank/conf/test.conf") + kotlin.concurrent.thread(isDaemon = true) { + bankCmd.run("serve -c ../bank/conf/test.conf") + } runBlocking { val client = HttpClient(CIO) { @@ -76,26 +84,9 @@ class IntegrationTest { } val nexusDb = NexusDb("postgresql:///libeufincheck") - val bankDb = BankDb("postgresql:///libeufincheck", "KUDOS", "EUR") - - bankDb.account.create( - login = "exchange", - password = "password", - name = "Mr Money", - internalPaytoUri = IbanPayTo(genIbanPaytoUri()), - isPublic = false, - isTalerExchange = true, - maxDebt = BankAmount("KUDOS:0"), - bonus = BankAmount("KUDOS:0") - ) - val userPayTo = IbanPayTo(genIbanPaytoUri()) val fiatPayTo = IbanPayTo(genIbanPaytoUri()) - kotlin.concurrent.thread(isDaemon = true) { - bankCmd.run("serve -c ../bank/conf/test.conf") - } - // Create user client.post("http://0.0.0.0:8080/accounts") { json {