commit 551831843d5f8e6651020cdc7bada26c4d63d4cf
parent 58d6b0aa414ca6a8a137ff6c4b301f502e8eccab
Author: Antoine A <>
Date: Wed, 1 Nov 2023 14:14:50 +0000
Fix add_incoming auth and clean tests
Diffstat:
5 files changed, 57 insertions(+), 77 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt
@@ -398,7 +398,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("balance_val"),
it.getInt("balance_frac"),
- getCurrency()
+ bankCurrency
),
credit_debit_indicator =
if (it.getBoolean("has_debt")) {
@@ -410,7 +410,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
debit_threshold = TalerAmount(
value = it.getLong("max_debt_val"),
frac = it.getInt("max_debt_frac"),
- getCurrency()
+ bankCurrency
)
)
}
@@ -543,7 +543,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
value = it.getLong("balance_val"),
frac = it.getInt("balance_frac"),
- currency = getCurrency()
+ currency = bankCurrency
),
credit_debit_indicator = if (it.getBoolean("balance_has_debt")) {
CorebankCreditDebitInfo.debit
@@ -554,7 +554,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
debit_threshold = TalerAmount(
value = it.getLong("max_debt_val"),
frac = it.getInt("max_debt_frac"),
- currency = getCurrency()
+ currency = bankCurrency
)
)
}
@@ -562,25 +562,6 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
// BANK ACCOUNTS
- suspend fun bankAccountSetMaxDebt(
- owningCustomerId: Long,
- maxDebt: TalerAmount
- ): Boolean = conn { conn ->
- val stmt = conn.prepareStatement("""
- UPDATE bank_accounts
- SET max_debt=(?,?)::taler_amount
- WHERE owning_customer_id=?
- """)
- stmt.setLong(1, maxDebt.value)
- stmt.setInt(2, maxDebt.frac)
- stmt.setLong(3, owningCustomerId)
- stmt.executeUpdateViolation()
- }
-
- private fun getCurrency(): String {
- return bankCurrency
- }
-
suspend fun bankAccountGetFromOwnerId(ownerId: Long): BankAccount? = conn { conn ->
val stmt = conn.prepareStatement("""
SELECT
@@ -605,7 +586,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
balance = TalerAmount(
it.getLong("balance_val"),
it.getInt("balance_frac"),
- getCurrency()
+ bankCurrency
),
owningCustomerId = it.getLong("owning_customer_id"),
hasDebt = it.getBoolean("has_debt"),
@@ -614,7 +595,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
maxDebt = TalerAmount(
value = it.getLong("max_debt_val"),
frac = it.getInt("max_debt_frac"),
- getCurrency()
+ bankCurrency
),
bankAccountId = it.getLong("bank_account_id")
)
@@ -647,7 +628,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
balance = TalerAmount(
it.getLong("balance_val"),
it.getInt("balance_frac"),
- getCurrency()
+ bankCurrency
),
owningCustomerId = it.getLong("owning_customer_id"),
hasDebt = it.getBoolean("has_debt"),
@@ -655,7 +636,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
maxDebt = TalerAmount(
value = it.getLong("max_debt_val"),
frac = it.getInt("max_debt_frac"),
- getCurrency()
+ bankCurrency
),
isPublic = it.getBoolean("is_public"),
bankAccountId = it.getLong("bank_account_id")
@@ -782,7 +763,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("amount_val"),
it.getInt("amount_frac"),
- getCurrency()
+ bankCurrency
),
accountServicerReference = it.getString("account_servicer_reference"),
endToEndId = it.getString("end_to_end_id"),
@@ -881,7 +862,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("amount_val"),
it.getInt("amount_frac"),
- getCurrency()
+ bankCurrency
),
subject = it.getString("subject"),
direction = TransactionDirection.valueOf(it.getString("direction"))
@@ -913,7 +894,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("amount_val"),
it.getInt("amount_frac"),
- getCurrency()
+ bankCurrency
),
debit_account = it.getString("debtor_payto_uri"),
reserve_pub = EddsaPublicKey(it.getBytes("reserve_pub")),
@@ -946,7 +927,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("amount_val"),
it.getInt("amount_frac"),
- getCurrency()
+ bankCurrency
),
credit_account = IbanPayTo(it.getString("creditor_payto_uri")),
wtid = ShortHashCode(it.getBytes("wtid")),
@@ -1005,7 +986,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amount = TalerAmount(
it.getLong("amount_val"),
it.getInt("amount_frac"),
- getCurrency()
+ bankCurrency
),
selectionDone = it.getBoolean("selection_done"),
selectedExchangePayto = it.getString("selected_exchange_payto")?.run(::IbanPayTo),
@@ -1284,19 +1265,19 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
amountDebit = TalerAmount(
value = it.getLong("amount_debit_val"),
frac = it.getInt("amount_debit_frac"),
- getCurrency()
+ bankCurrency
),
amountCredit = TalerAmount(
value = it.getLong("amount_credit_val"),
frac = it.getInt("amount_credit_frac"),
- getCurrency()
+ bankCurrency
),
bankAccount = it.getLong("bank_account"),
buyAtRatio = it.getInt("buy_at_ratio"),
buyInFee = TalerAmount(
value = it.getLong("buy_in_fee_val"),
frac = it.getInt("buy_in_fee_frac"),
- getCurrency()
+ bankCurrency
),
credit_payto_uri = it.getString("credit_payto_uri"),
cashoutCurrency = it.getString("cashout_currency"),
@@ -1306,7 +1287,7 @@ class Database(dbConfig: String, private val bankCurrency: String, private val f
sellOutFee = TalerAmount(
value = it.getLong("sell_out_fee_val"),
frac = it.getInt("sell_out_fee_frac"),
- getCurrency()
+ bankCurrency
),
subject = it.getString("subject"),
tanChannel = TanChannel.valueOf(it.getString("tan_channel")),
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
@@ -114,7 +114,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) {
historyEndpoint(::OutgoingHistory, Database::exchangeOutgoingPoolHistory)
}
}
- auth(db, TokenScope.readwrite) {
+ authAdmin(db, TokenScope.readwrite) {
post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-incoming") {
val req = call.receive<AddIncomingRequest>()
ctx.checkInternalCurrency(req.amount)
diff --git a/bank/src/test/kotlin/StatsTest.kt b/bank/src/test/kotlin/StatsTest.kt
@@ -32,11 +32,8 @@ import tech.libeufin.util.*
class StatsTest {
@Test
- fun transfer() = bankSetup { db ->
- assert(db.bankAccountSetMaxDebt(
- 2L,
- TalerAmount(1000, 0, "KUDOS")
- ))
+ fun transfer() = bankSetup { _ ->
+ setMaxDebt("exchange", TalerAmount("KUDOS:1000"))
suspend fun transfer(amount: TalerAmount) {
client.post("/accounts/exchange/taler-wire-gateway/transfer") {
diff --git a/bank/src/test/kotlin/WireGatewayApiTest.kt b/bank/src/test/kotlin/WireGatewayApiTest.kt
@@ -60,7 +60,7 @@ class WireGatewayApiTest {
}
// Test endpoint is correctly authenticated
- suspend fun ApplicationTestBuilder.authRoutine(path: String, body: JsonObject? = null, method: HttpMethod = HttpMethod.Post) {
+ suspend fun ApplicationTestBuilder.authRoutine(path: String, body: JsonObject? = null, method: HttpMethod = HttpMethod.Post, requireAdmin: Boolean = false) {
// No body when authentication must happen before parsing the body
// Unknown account
@@ -81,17 +81,28 @@ class WireGatewayApiTest {
basicAuth("exchange", "merchant-password")
}.assertUnauthorized()
+ if (requireAdmin) {
+ // Not exchange account
+ client.request(path) {
+ this.method = method
+ if (body != null) jsonBody(body)
+ basicAuth("merchant", "merchant-password")
+ }.assertUnauthorized()
+ }
+
// Not exchange account
client.request(path) {
this.method = method
if (body != null) jsonBody(body)
- basicAuth("merchant", "merchant-password")
+ if (requireAdmin)
+ basicAuth("admin", "admin-password")
+ else basicAuth("merchant", "merchant-password")
}.assertConflict().assertErr(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE)
}
// Testing the POST /transfer call from the TWG API.
@Test
- fun transfer() = bankSetup { db ->
+ fun transfer() = bankSetup { _ ->
val valid_req = json {
"request_uid" to randHashCode()
"amount" to "KUDOS:55"
@@ -109,10 +120,7 @@ class WireGatewayApiTest {
}.assertConflict().assertErr(TalerErrorCode.BANK_UNALLOWED_DEBIT)
// Giving debt allowance and checking the OK case.
- assert(db.bankAccountSetMaxDebt(
- 2L,
- TalerAmount(1000, 0, "KUDOS")
- ))
+ setMaxDebt("exchange", TalerAmount("KUDOS:1000"))
client.post("/accounts/exchange/taler-wire-gateway/transfer") {
basicAuth("exchange", "exchange-password")
jsonBody(valid_req)
@@ -216,12 +224,7 @@ class WireGatewayApiTest {
@Test
fun historyIncoming() = bankSetup { db ->
// Give Foo reasonable debt allowance:
- assert(
- db.bankAccountSetMaxDebt(
- 1L,
- TalerAmount(1000000, 0, "KUDOS")
- )
- )
+ setMaxDebt("merchant", TalerAmount("KUDOS:1000"))
suspend fun HttpResponse.assertHistory(size: Int) {
assertOk()
@@ -390,13 +393,7 @@ class WireGatewayApiTest {
*/
@Test
fun historyOutgoing() = bankSetup { db ->
- // Give Bar reasonable debt allowance:
- assert(
- db.bankAccountSetMaxDebt(
- 2L,
- TalerAmount(1000000, 0, "KUDOS")
- )
- )
+ setMaxDebt("exchange", TalerAmount("KUDOS:1000000"))
suspend fun HttpResponse.assertHistory(size: Int) {
assertOk()
@@ -505,41 +502,37 @@ class WireGatewayApiTest {
// Testing the /admin/add-incoming call from the TWG API.
@Test
- fun addIncoming() = bankSetup { db ->
+ fun addIncoming() = bankSetup { _ ->
val valid_req = json {
"amount" to "KUDOS:44"
"reserve_pub" to randEddsaPublicKey()
"debit_account" to "payto://iban/MERCHANT-IBAN-XYZ"
};
- authRoutine("/accounts/merchant/taler-wire-gateway/admin/add-incoming", valid_req)
+ authRoutine("/accounts/merchant/taler-wire-gateway/admin/add-incoming", valid_req, requireAdmin = true)
// Checking exchange debt constraint.
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(valid_req)
}.assertConflict().assertErr(TalerErrorCode.BANK_UNALLOWED_DEBIT)
// Giving debt allowance and checking the OK case.
- assert(db.bankAccountSetMaxDebt(
- 1L,
- TalerAmount(1000, 0, "KUDOS")
- ))
-
+ setMaxDebt("merchant", TalerAmount("KUDOS:1000"))
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(valid_req, deflate = true)
}.assertOk()
// Trigger conflict due to reused reserve_pub
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(valid_req)
}.assertConflict().assertErr(TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT)
// Currency mismatch
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(
json(valid_req) {
"amount" to "EUR:33"
@@ -549,7 +542,7 @@ class WireGatewayApiTest {
// Unknown account
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(
json(valid_req) {
"reserve_pub" to randEddsaPublicKey()
@@ -560,7 +553,7 @@ class WireGatewayApiTest {
// Same account
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(
json(valid_req) {
"reserve_pub" to randEddsaPublicKey()
@@ -571,7 +564,7 @@ class WireGatewayApiTest {
// Bad BASE32 reserve_pub
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(json(valid_req) {
"reserve_pub" to "I love chocolate"
})
@@ -579,7 +572,7 @@ class WireGatewayApiTest {
// Bad BASE32 len reserve_pub
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {
- basicAuth("exchange", "exchange-password")
+ basicAuth("admin", "admin-password")
jsonBody(json(valid_req) {
"reserve_pub" to randBase32Crockford(31)
})
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
@@ -83,6 +83,15 @@ fun dbSetup(lambda: suspend (Database) -> Unit) {
setup() { db, _ -> lambda(db) }
}
+/* ----- Common actions ----- */
+
+suspend fun ApplicationTestBuilder.setMaxDebt(account: String, maxDebt: TalerAmount) {
+ client.patch("/accounts/$account") {
+ basicAuth("admin", "admin-password")
+ jsonBody(json { "debit_threshold" to maxDebt })
+ }.assertNoContent()
+}
+
/* ----- Assert ----- */
fun HttpResponse.assertStatus(status: HttpStatusCode): HttpResponse {