commit 4acefbd1c6bcf1313be312851abe5a4ecf3f178f
parent cc9fcded04ca7b288a568644ba1edd90c6421159
Author: MS <ms@taler.net>
Date: Fri, 13 Jan 2023 14:33:45 +0100
Fix debit check on withdrawals.
Diffstat:
3 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/nexus/src/test/kotlin/SandboxAccessApiTest.kt b/nexus/src/test/kotlin/SandboxAccessApiTest.kt
@@ -60,6 +60,38 @@ class SandboxAccessApiTest {
}
}
}
+ @Test
+ fun withdrawWithHighBalance() {
+ withTestDatabase {
+ prepSandboxDb()
+ /**
+ * A problem appeared (Sandbox responding "insufficient funds")
+ * when B - A > T, where B is the balance, A the potential amount
+ * to withdraw and T is the debit threshold for the user. T is
+ * 1000 here, therefore setting B as 2000 and A as 1 should get
+ * this case tested.
+ */
+ wireTransfer(
+ "admin",
+ "foo",
+ "default",
+ "bring balance to high amount",
+ "TESTKUDOS:2000"
+ )
+ testApplication {
+ this.application(sandboxApp)
+ runBlocking {
+ // Normal, successful withdrawal.
+ client.post("/demobanks/default/access-api/accounts/foo/withdrawals") {
+ expectSuccess = true
+ setBody("{\"amount\": \"TESTKUDOS:1\"}")
+ contentType(ContentType.Application.Json)
+ basicAuth("foo", "foo")
+ }
+ }
+ }
+ }
+ }
// Check successful and failing case due to insufficient funds.
@Test
fun debitWithdraw() {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -1301,23 +1301,10 @@ val sandboxApp: Application.() -> Unit = {
val amount = parseAmount(req.amount)
if (amount.currency != demobank.currency)
throw badRequest("Currency ${amount.currency} differs from Demobank's: ${demobank.currency}")
- /**
- * Check for debit threshold. That's however also later checked
- * after the /confirm call. Username == null case is handled above.
- */
- val pendingBalance = getBalance(username!!, withPending = true)
- val maxDebt = if (username == "admin") {
- demobank.bankDebtLimit
- } else demobank.usersDebtLimit
- val amountAsNumber = BigDecimal(amount.amount)
- if ((pendingBalance - amountAsNumber).abs() > BigDecimal.valueOf(maxDebt.toLong())) {
- logger.info("User $username would surpass user debit " +
- "threshold of ${demobank.usersDebtLimit}. Rollback Taler withdrawal"
- )
- throw SandboxError(
- HttpStatusCode.Forbidden,
- "Insufficient funds."
- )
+ // Check funds are sufficient.
+ if (maybeDebit(maybeOwnedAccount.label, BigDecimal(amount.amount))) {
+ logger.error("Account ${maybeOwnedAccount.label} would surpass debit threshold. Not withdrawing")
+ throw SandboxError(HttpStatusCode.PreconditionFailed, "Insufficient funds")
}
val wo: TalerWithdrawalEntity = transaction {
TalerWithdrawalEntity.new {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
@@ -127,6 +127,7 @@ fun wireTransfer(
pmtInfId: String? = null
): String {
val parsedAmount = parseAmount(amount)
+ // Potential amount to transfer.
val amountAsNumber = BigDecimal(parsedAmount.amount)
if (amountAsNumber == BigDecimal.ZERO)
throw badRequest("Wire transfers of zero not possible.")