libeufin

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

commit 106f680ead96946a5f53e038ed29f46bd1e127ce
parent 0da939cafc5a9f456505ea9e85d8d98ba172c763
Author: Antoine A <>
Date:   Sat, 16 Dec 2023 16:26:50 +0000

Add unauthenticated withdrawal abort endpoint to Taler Bank Integration API and deprecate previous one

Diffstat:
MAPI_CHANGES.md | 2++
Mbank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt | 15+++++++++++++++
Mbank/src/main/kotlin/tech/libeufin/bank/Constants.kt | 4++--
Mbank/src/test/kotlin/BankIntegrationApiTest.kt | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Mbank/src/test/kotlin/CoreBankApiTest.kt | 50--------------------------------------------------
5 files changed, 69 insertions(+), 52 deletions(-)

diff --git a/API_CHANGES.md b/API_CHANGES.md @@ -17,6 +17,8 @@ This files contains all the API changes for the current release: - PATCH /accounts: fix PATCH semantic - PATCH /accounts: restrict PATCH contact_data to admin - POST /accounts/USERNAME/transactions: prohibit transaction to admin account +- Deprecate POST /accounts/USERNAME/withdrawals/WITHDRAWAL_ID/abort +- Add POST /taler-integration/withdrawal-operation/WITHDRAWAL_ID/abort ## bank cli diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt @@ -25,6 +25,7 @@ import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* +import io.ktor.http.* import net.taler.common.errorcodes.TalerErrorCode import tech.libeufin.bank.WithdrawalDAO.* import java.lang.AssertionError @@ -98,4 +99,18 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) { } } } + post("/taler-integration/withdrawal-operation/{wopid}/abort") { + val opId = call.uuidUriComponent("wopid") + when (db.withdrawal.abort(opId)) { + AbortResult.UnknownOperation -> throw notFound( + "Withdrawal operation $opId not found", + TalerErrorCode.BANK_TRANSACTION_NOT_FOUND + ) + AbortResult.AlreadyConfirmed -> throw conflict( + "Cannot abort confirmed withdrawal", + TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT + ) + AbortResult.Success -> call.respond(HttpStatusCode.NoContent) + } + } } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt @@ -42,7 +42,7 @@ const val MAX_BODY_LENGTH: Long = 4 * 1024 // 4kB const val MIN_VERSION: Int = 14 // API version -const val COREBANK_API_VERSION: String = "2:3:2" +const val COREBANK_API_VERSION: String = "3:0:3" const val CONVERSION_API_VERSION: String = "0:0:0" -const val INTEGRATION_API_VERSION: String = "1:0:1" +const val INTEGRATION_API_VERSION: String = "2:0:2" const val WIRE_GATEWAY_API_VERSION: String = "0:1:0" \ No newline at end of file diff --git a/bank/src/test/kotlin/BankIntegrationApiTest.kt b/bank/src/test/kotlin/BankIntegrationApiTest.kt @@ -139,6 +139,56 @@ class BankIntegrationApiTest { } } + // POST /taler-integration/withdrawal-operation/UUID/abort + @Test + fun abort() = bankSetup { _ -> + // TODO auth routine + // Check abort created + client.postA("/accounts/merchant/withdrawals") { + json { "amount" to "KUDOS:1" } + }.assertOkJson<BankAccountCreateWithdrawalResponse> { + val uuid = it.taler_withdraw_uri.split("/").last() + + // Check OK + client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() + // Check idempotence + client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() + } + + // Check abort selected + client.postA("/accounts/merchant/withdrawals") { + json { "amount" to "KUDOS:1" } + }.assertOkJson<BankAccountCreateWithdrawalResponse> { + val uuid = it.taler_withdraw_uri.split("/").last() + withdrawalSelect(uuid) + + // Check OK + client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() + // Check idempotence + client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() + } + + // Check abort confirmed + client.postA("/accounts/merchant/withdrawals") { + json { "amount" to "KUDOS:1" } + }.assertOkJson<BankAccountCreateWithdrawalResponse> { + val uuid = it.taler_withdraw_uri.split("/").last() + withdrawalSelect(uuid) + client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() + + // Check error + client.postA("/taler-integration/withdrawal-operation/$uuid/abort") + .assertConflict(TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT) + } + + // Check bad UUID + client.postA("/taler-integration/withdrawal-operation//chocolate/abort").assertBadRequest() + + // Check unknown + client.postA("/taler-integration/withdrawal-operation/${UUID.randomUUID()}/abort") + .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) + } + // Testing the generation of taler://withdraw-URIs. @Test fun testWithdrawUri() { diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -860,56 +860,6 @@ class CoreBankWithdrawalApiTest { .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } - // POST /accounts/USERNAME/withdrawals/withdrawal_id/abort - @Test - fun abort() = bankSetup { _ -> - // TODO auth routine - // Check abort created - client.postA("/accounts/merchant/withdrawals") { - json { "amount" to "KUDOS:1" } - }.assertOkJson<BankAccountCreateWithdrawalResponse> { - val uuid = it.taler_withdraw_uri.split("/").last() - - // Check OK - client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() - // Check idempotence - client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() - } - - // Check abort selected - client.postA("/accounts/merchant/withdrawals") { - json { "amount" to "KUDOS:1" } - }.assertOkJson<BankAccountCreateWithdrawalResponse> { - val uuid = it.taler_withdraw_uri.split("/").last() - withdrawalSelect(uuid) - - // Check OK - client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() - // Check idempotence - client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() - } - - // Check abort confirmed - client.postA("/accounts/merchant/withdrawals") { - json { "amount" to "KUDOS:1" } - }.assertOkJson<BankAccountCreateWithdrawalResponse> { - val uuid = it.taler_withdraw_uri.split("/").last() - withdrawalSelect(uuid) - client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() - - // Check error - client.postA("/accounts/merchant/withdrawals/$uuid/abort") - .assertConflict(TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT) - } - - // Check bad UUID - client.postA("/accounts/merchant/withdrawals/chocolate/abort").assertBadRequest() - - // Check unknown - client.postA("/accounts/merchant/withdrawals/${UUID.randomUUID()}/abort") - .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) - } - // POST /accounts/USERNAME/withdrawals/withdrawal_id/confirm @Test fun confirm() = bankSetup { _ ->