commit 303848df352f3515666f55f44b68d73315083b06
parent da2aa56eaf8ad545746eb7c8520b665980127523
Author: Antoine A <>
Date: Mon, 11 Dec 2023 12:26:41 +0000
Reuse common unknown account error
Diffstat:
5 files changed, 34 insertions(+), 51 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
@@ -245,10 +245,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) {
)
when (db.account.delete(username)) {
- AccountDeletionResult.UnknownAccount -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ AccountDeletionResult.UnknownAccount -> throw unknownAccount(username)
AccountDeletionResult.BalanceNotZero -> throw conflict(
"Account balance is not zero.",
TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO
@@ -262,10 +259,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) {
val req = call.receive<AccountReconfiguration>()
when (patchAccount(db, ctx, req, username, isAdmin)) {
AccountPatchResult.Success -> call.respond(HttpStatusCode.NoContent)
- AccountPatchResult.UnknownAccount -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ AccountPatchResult.UnknownAccount -> throw unknownAccount(username)
AccountPatchResult.NonAdminName -> throw conflict(
"non-admin user cannot change their legal name",
TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME
@@ -290,10 +284,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) {
}
when (db.account.reconfigPassword(username, req.new_password, req.old_password)) {
AccountPatchAuthResult.Success -> call.respond(HttpStatusCode.NoContent)
- AccountPatchAuthResult.UnknownAccount -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ AccountPatchAuthResult.UnknownAccount -> throw unknownAccount(username)
AccountPatchAuthResult.OldPasswordMismatch -> throw conflict(
"old password does not match",
TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD
@@ -323,10 +314,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) {
}
auth(db, TokenScope.readonly, allowAdmin = true) {
get("/accounts/{USERNAME}") {
- val account = db.account.get(username) ?: throw notFound(
- "Account '$username' not found.",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ val account = db.account.get(username) ?: throw unknownAccount(username)
call.respond(account)
}
}
@@ -370,10 +358,7 @@ private fun Routing.coreBankTransactionsApi(db: Database, ctx: BankConfig) {
timestamp = Instant.now(),
)
when (res) {
- is BankTransactionResult.UnknownDebtor -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ is BankTransactionResult.UnknownDebtor -> throw unknownAccount(username)
is BankTransactionResult.BothPartySame -> throw conflict(
"Wire transfer attempted with credit and debit party being the same bank account",
TalerErrorCode.BANK_SAME_ACCOUNT
@@ -399,10 +384,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) {
ctx.checkRegionalCurrency(req.amount)
val opId = UUID.randomUUID()
when (db.withdrawal.create(username, opId, req.amount)) {
- WithdrawalCreationResult.UnknownAccount -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ WithdrawalCreationResult.UnknownAccount -> throw unknownAccount(username)
WithdrawalCreationResult.AccountIsExchange -> throw conflict(
"Exchange account cannot perform withdrawal operation",
TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE
@@ -543,10 +525,7 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) = conditio
validityPeriod = TAN_VALIDITY_PERIOD
)
when (res) {
- is CashoutCreationResult.AccountNotFound -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ is CashoutCreationResult.AccountNotFound -> throw unknownAccount(username)
is CashoutCreationResult.BadConversion -> throw conflict(
"Wrong currency conversion",
TalerErrorCode.BANK_BAD_CONVERSION
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
@@ -30,7 +30,7 @@ import tech.libeufin.util.*
* and that is meant to be caught by Ktor and responded to the
* client.
*/
-class LibeufinBankException(
+class LibeufinException(
// Status code that Ktor will set for the response.
val httpStatus: HttpStatusCode,
// Error detail object, after Taler API.
@@ -61,7 +61,7 @@ suspend fun ApplicationCall.err(
error: TalerErrorCode
) {
err(
- LibeufinBankException(
+ LibeufinException(
httpStatus = status, talerError = TalerError(
code = error.code, err = error, hint = hint
)
@@ -70,7 +70,7 @@ suspend fun ApplicationCall.err(
}
suspend fun ApplicationCall.err(
- err: LibeufinBankException
+ err: LibeufinException
) {
attributes.put(LOG_MSG, "${err.talerError.err.name} ${err.talerError.hint}")
respond(
@@ -85,40 +85,44 @@ fun libeufinError(
hint: String?,
error: TalerErrorCode,
detail: String? = null
-): LibeufinBankException = LibeufinBankException(
+): LibeufinException = LibeufinException(
httpStatus = status, talerError = TalerError(
code = error.code, err = error, hint = hint, detail = detail
)
)
+/* ----- HTTP error ----- */
+
fun forbidden(
hint: String = "No rights on the resource",
error: TalerErrorCode = TalerErrorCode.END
-): LibeufinBankException = libeufinError(HttpStatusCode.Forbidden, hint, error)
+): LibeufinException = libeufinError(HttpStatusCode.Forbidden, hint, error)
fun unauthorized(
hint: String,
error: TalerErrorCode = TalerErrorCode.GENERIC_UNAUTHORIZED
-): LibeufinBankException = libeufinError(HttpStatusCode.Unauthorized, hint, error)
+): LibeufinException = libeufinError(HttpStatusCode.Unauthorized, hint, error)
-fun internalServerError(hint: String?): LibeufinBankException
+fun internalServerError(hint: String?): LibeufinException
= libeufinError(HttpStatusCode.InternalServerError, hint, TalerErrorCode.GENERIC_INTERNAL_INVARIANT_FAILURE)
fun notFound(
hint: String,
error: TalerErrorCode
-): LibeufinBankException = libeufinError(HttpStatusCode.NotFound, hint, error)
+): LibeufinException = libeufinError(HttpStatusCode.NotFound, hint, error)
fun conflict(
hint: String, error: TalerErrorCode
-): LibeufinBankException = libeufinError(HttpStatusCode.Conflict, hint, error)
+): LibeufinException = libeufinError(HttpStatusCode.Conflict, hint, error)
fun badRequest(
hint: String? = null,
error: TalerErrorCode = TalerErrorCode.GENERIC_JSON_INVALID,
detail: String? = null
-): LibeufinBankException = libeufinError(HttpStatusCode.BadRequest, hint, error, detail)
+): LibeufinException = libeufinError(HttpStatusCode.BadRequest, hint, error, detail)
+
+/* ----- Currency checks ----- */
fun BankConfig.checkRegionalCurrency(amount: TalerAmount) {
if (amount.currency != regionalCurrency) throw badRequest(
@@ -132,4 +136,13 @@ fun BankConfig.checkFiatCurrency(amount: TalerAmount) {
"Wrong currency: expected fiat currency $fiatCurrency got ${amount.currency}",
TalerErrorCode.GENERIC_CURRENCY_MISMATCH
)
+}
+
+/* ----- Common errors ----- */
+
+fun unknownAccount(id: String): LibeufinException {
+ return notFound(
+ "Account '$id' not found",
+ TalerErrorCode.BANK_UNKNOWN_ACCOUNT
+ )
}
\ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -141,7 +141,7 @@ fun Application.corebankWebApp(db: Database, ctx: BankConfig) {
install(StatusPages) {
exception<Exception> { call, cause ->
when (cause) {
- is LibeufinBankException -> call.err(cause)
+ is LibeufinException -> call.err(cause)
is SQLException -> {
when (cause.sqlState) {
PSQLState.SERIALIZATION_FAILURE.state -> call.err(
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
@@ -52,10 +52,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) {
now = Instant.now()
)
when (res) {
- is TransferResult.UnknownExchange -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ is TransferResult.UnknownExchange -> throw unknownAccount(username)
is TransferResult.NotAnExchange -> throw conflict(
"$username is not an exchange account.",
TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE
@@ -125,10 +122,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) {
now = timestamp
)
when (res) {
- is AddIncomingResult.UnknownExchange -> throw notFound(
- "Account '$username' not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ is AddIncomingResult.UnknownExchange -> throw unknownAccount(username)
is AddIncomingResult.NotAnExchange -> throw conflict(
"$username is not an exchange account.",
TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -49,10 +49,7 @@ fun ApplicationCall.expectUriComponent(componentName: String) =
/** Retrieve the bank account info for the selected username*/
suspend fun ApplicationCall.bankInfo(db: Database): BankInfo
- = db.account.bankInfo(username) ?: throw notFound(
- "Bank account for customer $username not found",
- TalerErrorCode.BANK_UNKNOWN_ACCOUNT
- )
+ = db.account.bankInfo(username) ?: throw unknownAccount(username)
// Generates a new Payto-URI with IBAN scheme.
fun genIbanPaytoUri(): String = "payto://iban/${getIban()}"