gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] 08/09: Error management.


From: gnunet
Subject: [libeufin] 08/09: Error management.
Date: Fri, 20 Jan 2023 16:49:42 +0100

This is an automated email from the git hooks/post-receive script.

ms pushed a commit to branch master
in repository libeufin.

commit 2a45c348a3506259e835bd0877fad9c3c5f55c4a
Author: MS <ms@taler.net>
AuthorDate: Fri Jan 20 16:26:34 2023 +0100

    Error management.
    
    Blaming the bank when a 'bank account' is not
    found for an existing 'customer'.
---
 .../kotlin/tech/libeufin/sandbox/CircuitApi.kt     | 29 ++++++++++-----
 .../main/kotlin/tech/libeufin/sandbox/Helpers.kt   | 41 +++++++++++++++++-----
 2 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
index 721b3c16..6d067ffd 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
@@ -6,6 +6,7 @@ import io.ktor.http.*
 import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
+import io.netty.handler.codec.http.HttpResponseStatus
 import org.jetbrains.exposed.sql.transactions.transaction
 import tech.libeufin.sandbox.CashoutOperationsTable.uuid
 import tech.libeufin.util.*
@@ -437,22 +438,25 @@ fun circuitApi(circuitRoute: Route) {
         throwIfInstitutionalName(resourceName)
         allowOwnerOrAdmin(username, resourceName)
         val customer = getCustomer(resourceName)
-        /** FIXME: the following query can 404, but should 500.
-         * The reason is that that's the bank's fault if an existing
-         * customer misses the bank account.  Check other calls too,
-         * for the same error.
+        /**
+         * CUSTOMER AND BANK ACCOUNT INVARIANT.
+         *
+         * After having found a 'customer' associated with the resourceName
+         * - see previous line -, the bank must ensure that a 'bank account'
+         * exist under the same resourceName.  If that fails, the bank broke 
the
+         * invariant and should respond 500.
          */
-        val bankAccount = getBankAccountFromLabel(resourceName)
+        val bankAccount = getBankAccountFromLabel(resourceName, withBankFault 
= true)
         /**
          * Throwing when name or cash-out address aren't found ensures
          * that the customer was indeed added via the Circuit API, as opposed
          * to the Access API.
          */
-        val potentialError = "$resourceName not managed by the Circuit API."
+        val maybeError = "$resourceName not managed by the Circuit API."
         call.respond(CircuitAccountInfo(
             username = customer.username,
-            name = customer.name ?: throw notFound(potentialError),
-            cashout_address = customer.cashout_address ?: throw 
notFound(potentialError),
+            name = customer.name ?: throw notFound(maybeError),
+            cashout_address = customer.cashout_address ?: throw 
notFound(maybeError),
             contact_data = CircuitContactData(
                 email = customer.email,
                 phone = customer.phone
@@ -480,6 +484,10 @@ fun circuitApi(circuitRoute: Route) {
                 })
             }
         }
+        if (customers.size == 0) {
+            call.respond(HttpStatusCode.NoContent)
+            return@get
+        }
         call.respond(object {val customers = customers})
         return@get
     }
@@ -597,8 +605,11 @@ fun circuitApi(circuitRoute: Route) {
         call.request.basicAuth(onlyAdmin = true)
         val resourceName = call.getUriComponent("resourceName")
         throwIfInstitutionalName(resourceName)
-        val bankAccount = getBankAccountFromLabel(resourceName)
         val customer = getCustomer(resourceName)
+        val bankAccount = getBankAccountFromLabel(
+            resourceName,
+            withBankFault = true // See comment "CUSTOMER AND BANK ACCOUNT 
INVARIANT".
+        )
         val balance = getBalance(bankAccount)
         if (balance != BigDecimal.ZERO)
             throw SandboxError(
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 693dc885..de22bf34 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -302,7 +302,18 @@ fun getBankAccountFromIban(iban: String): 
BankAccountEntity {
     )
 }
 
-fun getBankAccountFromLabel(label: String, demobank: String = "default"): 
BankAccountEntity {
+/**
+ * The argument 'withBankFault' represents the case where
+ * _the bank_ must ensure that a resource (in this case a bank
+ * account) exists.  For example, every 'customer' should have
+ * a 'bank account', and if a customer is found without a bank
+ * account, then the bank broke such condition.
+ */
+fun getBankAccountFromLabel(
+    label: String,
+    demobank: String = "default",
+    withBankFault: Boolean = false
+): BankAccountEntity {
     val maybeDemobank = getDemobank(demobank)
     if (maybeDemobank == null) {
         logger.error("Demobank '$demobank' not found")
@@ -311,21 +322,33 @@ fun getBankAccountFromLabel(label: String, demobank: 
String = "default"): BankAc
             "Demobank '$demobank' not found"
         )
     }
-    return getBankAccountFromLabel(label, maybeDemobank)
+    return getBankAccountFromLabel(
+        label,
+        maybeDemobank,
+        withBankFault
+    )
 }
-fun getBankAccountFromLabel(label: String,
-                            demobank: DemobankConfigEntity
+fun getBankAccountFromLabel(
+    label: String,
+    demobank: DemobankConfigEntity,
+    withBankFault: Boolean = false
 ): BankAccountEntity {
-    return transaction {
+    val maybeBankAccount = transaction {
         BankAccountEntity.find(
             BankAccountsTable.label eq label and (
                     BankAccountsTable.demoBank eq demobank.id
                     )
-        ).firstOrNull() ?: throw SandboxError(
-            HttpStatusCode.NotFound,
-            "Did not find a bank account for label $label"
-        )
+        ).firstOrNull()
     }
+    if (maybeBankAccount == null && withBankFault)
+        throw internalServerError(
+            "Bank account $label was not found, but it should."
+        )
+    if (maybeBankAccount == null)
+        throw notFound(
+            "Bank account $label was not found."
+        )
+    return maybeBankAccount
 }
 
 fun getBankAccountFromSubscriber(subscriber: EbicsSubscriberEntity): 
BankAccountEntity {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]