diff options
author | Antoine A <> | 2023-12-02 13:03:10 +0000 |
---|---|---|
committer | Antoine A <> | 2023-12-02 13:03:10 +0000 |
commit | 653fb27660f78b19fbef32137c5c91fc9ad61dcf (patch) | |
tree | 2cdcd4b2aa0b874e7988c2b3d8774182db0516d3 | |
parent | 8e43b5d1810956eaad533f9849dcf05fe176ab43 (diff) | |
download | libeufin-653fb27660f78b19fbef32137c5c91fc9ad61dcf.tar.gz libeufin-653fb27660f78b19fbef32137c5c91fc9ad61dcf.tar.bz2 libeufin-653fb27660f78b19fbef32137c5c91fc9ad61dcf.zip |
Single DEFAULT_DEBT_LIMIT config
-rw-r--r-- | bank/conf/test.conf | 3 | ||||
-rw-r--r-- | bank/conf/test_bonus.conf | 1 | ||||
-rw-r--r-- | bank/conf/test_no_conversion.conf | 1 | ||||
-rw-r--r-- | bank/conf/test_no_tan.conf | 3 | ||||
-rw-r--r-- | bank/conf/test_restrict.conf | 3 | ||||
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/Config.kt | 6 | ||||
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 66 | ||||
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/Main.kt | 22 | ||||
-rw-r--r-- | bank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 2 | ||||
-rw-r--r-- | bank/src/test/kotlin/CoreBankApiTest.kt | 4 | ||||
-rw-r--r-- | bank/src/test/kotlin/RevenueApiTest.kt | 2 | ||||
-rw-r--r-- | bank/src/test/kotlin/StatsTest.kt | 6 | ||||
-rw-r--r-- | bank/src/test/kotlin/WireGatewayApiTest.kt | 8 | ||||
-rw-r--r-- | bank/src/test/kotlin/helpers.kt | 2 | ||||
-rw-r--r-- | contrib/bank.conf | 31 | ||||
-rw-r--r-- | debian/etc/libeufin/libeufin-bank.conf | 15 | ||||
-rw-r--r-- | integration/conf/integration.conf | 2 | ||||
-rw-r--r-- | integration/test/IntegrationTest.kt | 10 |
18 files changed, 87 insertions, 100 deletions
diff --git a/bank/conf/test.conf b/bank/conf/test.conf index afa4530b..96d80b0f 100644 --- a/bank/conf/test.conf +++ b/bank/conf/test.conf @@ -1,7 +1,6 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:100 -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 +DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/bank/conf/test_bonus.conf b/bank/conf/test_bonus.conf index 09bb5146..b6126109 100644 --- a/bank/conf/test_bonus.conf +++ b/bank/conf/test_bonus.conf @@ -1,6 +1,5 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 REGISTRATION_BONUS = KUDOS:100 ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/bank/conf/test_no_conversion.conf b/bank/conf/test_no_conversion.conf index ac67d6e4..b1912331 100644 --- a/bank/conf/test_no_conversion.conf +++ b/bank/conf/test_no_conversion.conf @@ -1,6 +1,5 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/bank/conf/test_no_tan.conf b/bank/conf/test_no_tan.conf index 5bf08d43..c031f3fc 100644 --- a/bank/conf/test_no_tan.conf +++ b/bank/conf/test_no_tan.conf @@ -1,7 +1,6 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:100 -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 +DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com allow_conversion = YES FIAT_CURRENCY = EUR diff --git a/bank/conf/test_restrict.conf b/bank/conf/test_restrict.conf index 1aae6252..e1aa4f76 100644 --- a/bank/conf/test_restrict.conf +++ b/bank/conf/test_restrict.conf @@ -1,7 +1,6 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:100 -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 +DEFAULT_DEBT_LIMIT = KUDOS:100 allow_conversion = YES FIAT_CURRENCY = EUR diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt index a9ea31cc..6a7cd046 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt @@ -37,8 +37,7 @@ data class BankConfig( val regionalCurrencySpec: CurrencySpecification, val allowRegistration: Boolean, val allowAccountDeletion: Boolean, - val defaultCustomerDebtLimit: TalerAmount, - val defaultAdminDebtLimit: TalerAmount, + val defaultDebtLimit: TalerAmount, val registrationBonus: TalerAmount, val suggestedWithdrawalExchange: String?, /** @@ -110,8 +109,7 @@ fun TalerConfig.loadBankConfig(): BankConfig { regionalCurrencySpec = currencySpecificationFor(regionalCurrency), allowRegistration = lookupBoolean("libeufin-bank", "allow_registration") ?: false, allowAccountDeletion = lookupBoolean("libeufin-bank", "allow_account_deletion") ?: false, - defaultCustomerDebtLimit = amount("libeufin-bank", "default_customer_debt_limit", regionalCurrency) ?: TalerAmount(0, 0, regionalCurrency), - defaultAdminDebtLimit = amount("libeufin-bank", "default_admin_debt_limit", regionalCurrency) ?: TalerAmount(0, 0, regionalCurrency), + defaultDebtLimit = amount("libeufin-bank", "default_debt_limit", regionalCurrency) ?: TalerAmount(0, 0, regionalCurrency), registrationBonus = amount("libeufin-bank", "registration_bonus", regionalCurrency) ?: TalerAmount(0, 0, regionalCurrency), suggestedWithdrawalExchange = lookupString("libeufin-bank", "suggested_withdrawal_exchange"), spaCaptchaURL = lookupString("libeufin-bank", "spa_captcha_url"), diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt index 7e165446..060b1bdd 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -135,41 +135,45 @@ private fun Routing.coreBankTokenApi(db: Database) { } } +suspend fun createAccount(db: Database, ctx: BankConfig, req: RegisterAccountRequest, isAdmin: Boolean): Pair<AccountCreationResult, IbanPayTo> { + // Prohibit reserved usernames: + if (RESERVED_ACCOUNTS.contains(req.username)) + throw conflict( + "Username '${req.username}' is reserved.", + TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT + ) + + if (req.debit_threshold != null && !isAdmin) + throw conflict( + "only admin account can choose the debit limit", + TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT + ) + + + val internalPayto = req.internal_payto_uri ?: IbanPayTo(genIbanPaytoUri()) + val res = db.account.create( + login = req.username, + name = req.name, + email = req.challenge_contact_data?.email, + phone = req.challenge_contact_data?.phone, + cashoutPayto = req.cashout_payto_uri, + password = req.password, + internalPaytoUri = internalPayto, + isPublic = req.is_public, + isTalerExchange = req.is_taler_exchange, + maxDebt = req.debit_threshold ?: ctx.defaultDebtLimit, + bonus = if (!req.is_taler_exchange) ctx.registrationBonus + else TalerAmount(0, 0, ctx.regionalCurrency), + checkPaytoIdempotent = req.internal_payto_uri != null + ) + return Pair(res, internalPayto) +} + private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { authAdmin(db, TokenScope.readwrite, !ctx.allowRegistration) { post("/accounts") { val req = call.receive<RegisterAccountRequest>() - // Prohibit reserved usernames: - if (RESERVED_ACCOUNTS.contains(req.username)) - throw conflict( - "Username '${req.username}' is reserved.", - TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT - ) - - if (req.debit_threshold != null && !isAdmin) - throw conflict( - "only admin account can choose the debit limit", - TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT - ) - - - val internalPayto = req.internal_payto_uri ?: IbanPayTo(genIbanPaytoUri()) - val result = db.account.create( - login = req.username, - name = req.name, - email = req.challenge_contact_data?.email, - phone = req.challenge_contact_data?.phone, - cashoutPayto = req.cashout_payto_uri, - password = req.password, - internalPaytoUri = internalPayto, - isPublic = req.is_public, - isTalerExchange = req.is_taler_exchange, - maxDebt = req.debit_threshold ?: ctx.defaultCustomerDebtLimit, - bonus = if (!req.is_taler_exchange) ctx.registrationBonus - else TalerAmount(0, 0, ctx.regionalCurrency), - checkPaytoIdempotent = req.internal_payto_uri != null - ) - + val (result, internalPayto) = createAccount(db, ctx, req, isAdmin); when (result) { AccountCreationResult.BonusBalanceInsufficient -> throw conflict( "Insufficient admin funds to grant bonus", diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt index 71edb958..a1e28cf9 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -339,27 +339,7 @@ class CreateAccount : CliktCommand("Create an account", name = "create-account") val dbCfg = cfg.loadDbConfig() val db = Database(dbCfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency) runBlocking { - if (RESERVED_ACCOUNTS.contains(json.username)) { - throw Exception("Username '${json.username}' is reserved") - } - - 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), - checkPaytoIdempotent = json.internal_payto_uri != null - ) - + val (result, internalPayto) = createAccount(db, ctx, json, true); when (result) { AccountCreationResult.BonusBalanceInsufficient -> throw Exception("Insufficient admin funds to grant bonus") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt index dc65fd44..2fdb957c 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -131,7 +131,7 @@ suspend fun maybeCreateAdminAccount(db: Database, ctx: BankConfig, pw: String? = internalPaytoUri = IbanPayTo(genIbanPaytoUri()), isPublic = false, isTalerExchange = false, - maxDebt = ctx.defaultAdminDebtLimit, + maxDebt = ctx.defaultDebtLimit, bonus = TalerAmount(0, 0, ctx.regionalCurrency), checkPaytoIdempotent = false ) diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt index c880be59..dedca301 100644 --- a/bank/src/test/kotlin/CoreBankApiTest.kt +++ b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -261,13 +261,15 @@ class CoreBankAccountsApiTest { // Test account created with bonus @Test - fun createBonus() = bankSetup(conf = "test_bonus.conf") { _ -> + fun createBonus() = bankSetup(conf = "test_bonus.conf") { _ -> val req = obj { "username" to "foo" "password" to "xyz" "name" to "Mallory" } + setMaxDebt("admin", "KUDOS:10000") + // Check ok repeat(100) { client.post("/accounts") { diff --git a/bank/src/test/kotlin/RevenueApiTest.kt b/bank/src/test/kotlin/RevenueApiTest.kt index 4432ce54..0a8a052a 100644 --- a/bank/src/test/kotlin/RevenueApiTest.kt +++ b/bank/src/test/kotlin/RevenueApiTest.kt @@ -32,7 +32,7 @@ class RevenueApiTest { // GET /accounts/{USERNAME}/taler-revenue/history @Test fun history() = bankSetup { - setMaxDebt("exchange", TalerAmount("KUDOS:1000000")) + setMaxDebt("exchange", "KUDOS:1000000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-revenue/history") historyRoutine<MerchantIncomingHistory>( url = "/accounts/merchant/taler-revenue/history", diff --git a/bank/src/test/kotlin/StatsTest.kt b/bank/src/test/kotlin/StatsTest.kt index 98184805..981eb34d 100644 --- a/bank/src/test/kotlin/StatsTest.kt +++ b/bank/src/test/kotlin/StatsTest.kt @@ -33,9 +33,9 @@ import tech.libeufin.util.* class StatsTest { @Test fun register() = bankSetup { db -> - setMaxDebt("merchant", TalerAmount("KUDOS:1000")) - setMaxDebt("exchange", TalerAmount("KUDOS:1000")) - setMaxDebt("customer", TalerAmount("KUDOS:1000")) + setMaxDebt("merchant", "KUDOS:1000") + setMaxDebt("exchange", "KUDOS:1000") + setMaxDebt("customer", "KUDOS:1000") suspend fun cashin(amount: String) { db.conn { conn -> diff --git a/bank/src/test/kotlin/WireGatewayApiTest.kt b/bank/src/test/kotlin/WireGatewayApiTest.kt index 654cdcc5..65a890a9 100644 --- a/bank/src/test/kotlin/WireGatewayApiTest.kt +++ b/bank/src/test/kotlin/WireGatewayApiTest.kt @@ -50,7 +50,7 @@ class WireGatewayApiTest { }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Giving debt allowance and checking the OK case. - setMaxDebt("exchange", TalerAmount("KUDOS:1000")) + setMaxDebt("exchange", "KUDOS:1000") client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() @@ -128,7 +128,7 @@ class WireGatewayApiTest { @Test fun historyIncoming() = bankSetup { // Give Foo reasonable debt allowance: - setMaxDebt("merchant", TalerAmount("KUDOS:1000")) + setMaxDebt("merchant", "KUDOS:1000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/history/incoming") historyRoutine<IncomingHistory>( url = "/accounts/exchange/taler-wire-gateway/history/incoming", @@ -166,7 +166,7 @@ class WireGatewayApiTest { */ @Test fun historyOutgoing() = bankSetup { - setMaxDebt("exchange", TalerAmount("KUDOS:1000000")) + setMaxDebt("exchange", "KUDOS:1000000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/history/outgoing") historyRoutine<OutgoingHistory>( url = "/accounts/exchange/taler-wire-gateway/history/outgoing", @@ -211,7 +211,7 @@ class WireGatewayApiTest { }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Giving debt allowance and checking the OK case. - setMaxDebt("merchant", TalerAmount("KUDOS:1000")) + setMaxDebt("merchant", "KUDOS:1000") client.postA("/accounts/exchange/taler-wire-gateway/admin/add-incoming") { json(valid_req, deflate = true) }.assertOk() diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt index 7d65e2f8..00830bb6 100644 --- a/bank/src/test/kotlin/helpers.kt +++ b/bank/src/test/kotlin/helpers.kt @@ -138,7 +138,7 @@ fun dbSetup(lambda: suspend (Database) -> Unit) { /* ----- Common actions ----- */ /** Set [account] debit threshold to [maxDebt] amount */ -suspend fun ApplicationTestBuilder.setMaxDebt(account: String, maxDebt: TalerAmount) { +suspend fun ApplicationTestBuilder.setMaxDebt(account: String, maxDebt: String) { client.patch("/accounts/$account") { pwAuth("admin") json { "debit_threshold" to maxDebt } diff --git a/contrib/bank.conf b/contrib/bank.conf index 7d6ca375..70b2690a 100644 --- a/contrib/bank.conf +++ b/contrib/bank.conf @@ -1,46 +1,43 @@ [libeufin-bank] # Internal currency of the libeufin-bank -#CURRENCY = KUDOS +# CURRENCY = KUDOS -# Default debt limit for newly created customer accounts Default is CURRENCY:0 -#DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:200 - -# Default debt limit of the admin. Typically higher, since sign-up bonuses and cashin are deducted from the admin account. Default is CURRENCY:0 -#DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:20000000 +# Default debt limit for newly created accounts Default is CURRENCY:0 +# DEFAULT_DEBT_LIMIT = KUDOS:200 # Value of the registration bonus for new users. Default is CURRENCY:0 -#REGISTRATION_BONUS = KUDOS:100 +# REGISTRATION_BONUS = KUDOS:100 # Allow account registration by anyone. -#ALLOW_REGISTRATION = yes +# ALLOW_REGISTRATION = no # Allow an account to delete itself -#ALLOW_ACCOUNT_DELETION = yes +# ALLOW_ACCOUNT_DELETION = no # Enable regional currency conversion -#ALLOW_CONVERSION = no +# ALLOW_CONVERSION = no # External currency used during cashin and cashout -#FIAT_CURRENCY = EUR +# FIAT_CURRENCY = EUR # Path to TAN challenge transmission script via sms. If not specified, this TAN channel will not be supported. -#TAN_SMS = +# TAN_SMS = # Path to TAN challenge transmission script via email. If not specified, this TAN channel will not be supported. -#TAN_EMAIL = +# TAN_EMAIL = # How "libeufin-bank serve" serves its API, this can either be tcp or unix -#SERVE = tcp +# SERVE = tcp # Port on which the HTTP server listens, e.g. 9967. Only used if SERVE is tcp. -#PORT = 8080 +# PORT = 8080 # Which unix domain path should we bind to? Only used if SERVE is unix. -#UNIXPATH = libeufin-bank.sock +# UNIXPATH = libeufin-bank.sock # What should be the file access permissions for UNIXPATH? Only used if SERVE is unix. -#UNIXPATH_MODE = 660 +# UNIXPATH_MODE = 660 # Path to spa files diff --git a/debian/etc/libeufin/libeufin-bank.conf b/debian/etc/libeufin/libeufin-bank.conf index 597ceb7b..71fb9fa4 100644 --- a/debian/etc/libeufin/libeufin-bank.conf +++ b/debian/etc/libeufin/libeufin-bank.conf @@ -5,17 +5,20 @@ # Internal currency of the libeufin-bank CURRENCY = KUDOS -# Default debt limit for newly created customer accounts -# DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:0 +# Default debt limit for newly created accounts +# DEFAULT_DEBT_LIMIT = KUDOS:0 -# Value of the registration bonus for new users. Default is "CURRENCY:0" +# Value of the registration bonus for new users # REGISTRATION_BONUS = KUDOS:0 -# Allow account registration by anyone. -# ALLOW_REGISTRATION = yes +# Allow account registration by anyone +# ALLOW_REGISTRATION = no # Allow an account to delete itself -# ALLOW_ACCOUNT_DELETION = yes +# ALLOW_ACCOUNT_DELETION = no + +# Enable regional currency conversion +# ALLOW_CONVERSION = no # Path to TAN challenge transmission script via sms. If not specified, this TAN channel wil be unuspported. TAN_SMS = diff --git a/integration/conf/integration.conf b/integration/conf/integration.conf index 07feee27..55a3d871 100644 --- a/integration/conf/integration.conf +++ b/integration/conf/integration.conf @@ -1,7 +1,5 @@ [libeufin-bank] CURRENCY = KUDOS -DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:100 -DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:10000 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/integration/test/IntegrationTest.kt b/integration/test/IntegrationTest.kt index 315e230e..e0bc237a 100644 --- a/integration/test/IntegrationTest.kt +++ b/integration/test/IntegrationTest.kt @@ -103,12 +103,14 @@ class IntegrationTest { // Create user client.post("http://0.0.0.0:8080/accounts") { + basicAuth("admin", "password") json { "username" to "customer" "password" to "password" "name" to "JohnSmith" "internal_payto_uri" to userPayTo "cashout_payto_uri" to fiatPayTo + "debit_threshold" to "KUDOS:100" "challenge_contact_data" to obj { "phone" to "+99" } @@ -132,6 +134,14 @@ class IntegrationTest { } }.assertNoContent() + // Set admin debit threshold + client.patch("http://0.0.0.0:8080/accounts/admin") { + basicAuth("admin", "password") + json { + "debit_threshold" to "KUDOS:1000" + } + }.assertNoContent() + // Cashin repeat(3) { i -> val reservePub = randBytes(32); |