diff options
author | Antoine A <> | 2023-12-05 09:25:40 +0000 |
---|---|---|
committer | Antoine A <> | 2023-12-05 09:25:40 +0000 |
commit | 93f3157833a87ef7efbd8c6d9efcdb0fa6862c62 (patch) | |
tree | abbf01bacf19d573a7ae4799ad99ecde8fac9291 | |
parent | 319cdd9ea4003f1d96ab1258d719b42364eebbbc (diff) | |
download | libeufin-93f3157833a87ef7efbd8c6d9efcdb0fa6862c62.tar.gz libeufin-93f3157833a87ef7efbd8c6d9efcdb0fa6862c62.tar.bz2 libeufin-93f3157833a87ef7efbd8c6d9efcdb0fa6862c62.zip |
Add edit-account command
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 41 | ||||
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/Main.kt | 67 | ||||
-rw-r--r-- | integration/test/IntegrationTest.kt | 9 |
3 files changed, 86 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 index 828c2e77..822f9983 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -170,6 +170,27 @@ suspend fun createAccount(db: Database, ctx: BankConfig, req: RegisterAccountReq return Pair(res, internalPayto) } +suspend fun patchAccount(db: Database, ctx: BankConfig, req: AccountReconfiguration, username: String, isAdmin: Boolean): AccountPatchResult { + req.debit_threshold?.run { ctx.checkRegionalCurrency(this) } + + if ((req.is_taler_exchange ?: false) == true && username == "admin") + throw conflict( + "admin account cannot be an exchange", + TalerErrorCode.BANK_PATCH_ADMIN_EXCHANGE + ) + + return db.account.reconfig( + login = username, + name = req.name, + cashoutPayto = req.cashout_payto_uri, + emailAddress = req.challenge_contact_data?.email, + isTalerExchange = req.is_taler_exchange, + phoneNumber = req.challenge_contact_data?.phone, + debtLimit = req.debit_threshold, + isAdmin = isAdmin + ) +} + private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { authAdmin(db, TokenScope.readwrite, !ctx.allowRegistration) { post("/accounts") { @@ -227,25 +248,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { auth(db, TokenScope.readwrite, allowAdmin = true) { patch("/accounts/{USERNAME}") { val req = call.receive<AccountReconfiguration>() - req.debit_threshold?.run { ctx.checkRegionalCurrency(this) } - - if ((req.is_taler_exchange ?: false) == true && username == "admin") - throw conflict( - "admin account cannot be an exchange", - TalerErrorCode.BANK_PATCH_ADMIN_EXCHANGE - ) - - val res = db.account.reconfig( - login = username, - name = req.name, - cashoutPayto = req.cashout_payto_uri, - emailAddress = req.challenge_contact_data?.email, - isTalerExchange = req.is_taler_exchange, - phoneNumber = req.challenge_contact_data?.phone, - debtLimit = req.debit_threshold, - isAdmin = isAdmin - ) - when (res) { + when (patchAccount(db, ctx, req, username, isAdmin)) { AccountPatchResult.Success -> call.respond(HttpStatusCode.NoContent) AccountPatchResult.UnknownAccount -> throw notFound( "Account '$username' not found", diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt index 45f59b33..d9cdf9d6 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -22,6 +22,7 @@ package tech.libeufin.bank import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands +import com.github.ajalt.clikt.parameters.types.* import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.groups.* @@ -217,7 +218,11 @@ class CommonOption: OptionGroup() { val config by option( "--config", "-c", help = "Specifies the configuration file" - ) + ).path( + mustExist = true, + canBeDir = false, + mustBeReadable = true, + ).convert { it.toString() } // TODO take path to load config } class BankDbInit : CliktCommand("Initialize the libeufin-bank database", name = "dbinit") { @@ -304,8 +309,11 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve") class ChangePw : CliktCommand("Change account password", name = "passwd") { private val common by CommonOption() - private val username by argument("username") - private val password by argument("password") + private val username by argument("username", help = "Account username") + private val password by argument( + "password", + help = "Account password used for authentication" + ) override fun run() = cliCmd(logger) { val cfg = talerConfig(common.config) @@ -325,6 +333,57 @@ class ChangePw : CliktCommand("Change account password", name = "passwd") { } } + +class EditAccount : CliktCommand( + "Edit an existing account", + name = "edit-account" +) { + private val common by CommonOption() + private val username: String by argument( + "username", + help = "Account username" + ) + private val name: String? by option( + help = "Legal name of the account owner" + ) + private val exchange: Boolean? by option( + help = "Make this account a taler exchange" + ).boolean() + private val email: String? by option(help = "E-Mail address used for TAN transmission") + private val phone: String? by option(help = "Phone number used for TAN transmission") + private val cashout_payto_uri: IbanPayTo? by option(help = "Payto URI of a fiant account who receive cashout amount").convert { IbanPayTo(it) } + private val debit_threshold: TalerAmount? by option(help = "Max debit allowed for this account").convert { TalerAmount(it) } + + override fun run() = cliCmd(logger) { + val cfg = talerConfig(common.config) + val ctx = cfg.loadBankConfig() + val dbCfg = cfg.loadDbConfig() + val db = Database(dbCfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency) + runBlocking { + val req = AccountReconfiguration( + name = name, + is_taler_exchange = exchange, + challenge_contact_data = ChallengeContactData( + email = email, + phone = phone, + ), + cashout_payto_uri = cashout_payto_uri, + debit_threshold = debit_threshold + ) + when (patchAccount(db, ctx, req, username, true)) { + AccountPatchResult.Success -> + logger.info("Account '$username' edited") + AccountPatchResult.UnknownAccount -> + throw Exception("Account '$username' not found") + AccountPatchResult.NonAdminLegalName -> + throw Exception("non-admin user cannot change their legal name") + AccountPatchResult.NonAdminDebtLimit -> + throw Exception("non-admin user cannot change their debt limit") + } + } + } +} + class CreateAccountOption: OptionGroup() { val username: String by option( "--username", "-u", @@ -402,7 +461,7 @@ class CreateAccount : CliktCommand( class LibeufinBankCommand : CliktCommand() { init { versionOption(getVersion()) - subcommands(ServeBank(), BankDbInit(), CreateAccount(), ChangePw(), CliConfigCmd(BANK_CONFIG_SOURCE)) + subcommands(ServeBank(), BankDbInit(), CreateAccount(), EditAccount(), ChangePw(), CliConfigCmd(BANK_CONFIG_SOURCE)) } override fun run() = Unit diff --git a/integration/test/IntegrationTest.kt b/integration/test/IntegrationTest.kt index 404cd5ce..5820a205 100644 --- a/integration/test/IntegrationTest.kt +++ b/integration/test/IntegrationTest.kt @@ -85,6 +85,7 @@ class IntegrationTest { nexusCmd.run("dbinit -c conf/integration.conf -r") bankCmd.run("dbinit -c conf/integration.conf -r") bankCmd.run("passwd admin password -c conf/integration.conf") + bankCmd.run("edit-account admin --debit_threshold KUDOS:1000 -c conf/integration.conf") bankCmd.run("create-account -c conf/integration.conf -u exchange -p password --name 'Mr Money' --exchange") kotlin.concurrent.thread(isDaemon = true) { bankCmd.run("serve -c conf/integration.conf") @@ -128,14 +129,6 @@ class IntegrationTest { } }.assertNoContent() - // Set admin debit threshold - client.patch("http://0.0.0.0:8090/accounts/admin") { - basicAuth("admin", "password") - json { - "debit_threshold" to "KUDOS:1000" - } - }.assertNoContent() - // Cashin repeat(3) { i -> val reservePub = randBytes(32); |