gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: Addressing #7788


From: gnunet
Subject: [libeufin] branch master updated: Addressing #7788
Date: Fri, 07 Apr 2023 17:14:58 +0200

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

ms pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new 101fa06f Addressing #7788
101fa06f is described below

commit 101fa06fd5fa863a90eb4cbc0b4fcd2e28fda583
Author: MS <ms@taler.net>
AuthorDate: Fri Apr 7 17:14:50 2023 +0200

    Addressing #7788
---
 cli/tests/launch_services.sh                       |  6 +-
 nexus/src/test/kotlin/MakeEnv.kt                   | 18 +++++-
 nexus/src/test/kotlin/SandboxCircuitApiTest.kt     | 66 ++++++++++++++++++++++
 nexus/src/test/kotlin/SandboxLegacyApiTest.kt      |  1 -
 .../kotlin/tech/libeufin/sandbox/CircuitApi.kt     | 36 ++++++++----
 .../main/kotlin/tech/libeufin/sandbox/Helpers.kt   |  2 +-
 .../kotlin/tech/libeufin/sandbox/bankAccount.kt    | 14 ++++-
 7 files changed, 124 insertions(+), 19 deletions(-)

diff --git a/cli/tests/launch_services.sh b/cli/tests/launch_services.sh
index f085fb26..2a5e10c5 100755
--- a/cli/tests/launch_services.sh
+++ b/cli/tests/launch_services.sh
@@ -4,8 +4,8 @@
 # connected through x-libeufin-bank.
 set -eu
 
-WITH_TASKS=1
-# WITH_TASKS=0
+# WITH_TASKS=1
+WITH_TASKS=0
 function exit_cleanup()
 {
   echo "Running exit-cleanup"
@@ -41,7 +41,7 @@ libeufin-sandbox \
 echo DONE
 echo -n Start the bank...
 export LIBEUFIN_SANDBOX_ADMIN_PASSWORD=foo
-libeufin-sandbox serve &> sandbox.log &
+libeufin-sandbox serve > sandbox.log 2>&1 &
 SANDBOX_PID=$!
 echo DONE
 echo -n Wait for the bank...
diff --git a/nexus/src/test/kotlin/MakeEnv.kt b/nexus/src/test/kotlin/MakeEnv.kt
index 596b2c95..b3c2e221 100644
--- a/nexus/src/test/kotlin/MakeEnv.kt
+++ b/nexus/src/test/kotlin/MakeEnv.kt
@@ -278,11 +278,23 @@ fun prepSandboxDb(usersDebtLimit: Int = 1000) {
             name = "Bar"
             cashout_address = "payto://iban/FIAT"
         }
+        // Note: exchange doesn't have the cash-out address.
         DemobankCustomerEntity.new {
-            username = "baz"
+            username = "exchange-0"
             passwordHash = CryptoUtil.hashpw("foo")
-            name = "Baz"
-            cashout_address = "payto://iban/OTHERBANK"
+            name = "Exchange"
+        }
+        BankAccountEntity.new {
+            iban = "AT561936082973364859"
+            /**
+             * For now, keep same semantics of Pybank: a username
+             * is AS WELL a bank account label.  In other words, it
+             * identifies a customer AND a bank account.
+             */
+            label = "exchange-0"
+            owner = "exchange-0"
+            this.demoBank = demoBank
+            isPublic = false
         }
     }
 }
diff --git a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt 
b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
index d9ff3d51..8ac0d1dc 100644
--- a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
@@ -11,12 +11,78 @@ import org.jetbrains.exposed.sql.transactions.transaction
 import org.junit.Ignore
 import org.junit.Test
 import tech.libeufin.sandbox.*
+import tech.libeufin.util.getIban
 import tech.libeufin.util.parseAmount
 import java.io.File
 import java.math.BigDecimal
 import java.util.*
 
 class SandboxCircuitApiTest {
+
+    /**
+     * Testing that the admin is able to conduct ordinary
+     * account operations even on non-circuit accounts.  Recall:
+     * such accounts are just those without the cash-out address.
+     */
+    @Test
+    fun opOnNonCircuitAccounts() {
+        withTestDatabase {
+            testApplication {
+                prepSandboxDb()
+                testApplication {
+                    application(sandboxApp)
+                    // Only testing that this doesn't except.
+                    client.get("/demobanks/default/circuit-api/accounts") {
+                        expectSuccess = true
+                        basicAuth("admin", "foo")
+                    }
+                    // Trying to PATCH non circuit account
+                    
client.patch("/demobanks/default/circuit-api/accounts/exchange-0") {
+                        expectSuccess = true
+                        basicAuth("admin", "foo")
+                        contentType(ContentType.Application.Json)
+                        setBody("""
+                            {"name": "Exchange 0",
+                             "contact_data": {},
+                             "cashout_address": 
"payto://iban/SANDBOXX/${getIban()}"
+                             }
+                        """.trimIndent())
+                    }
+                    // PATCH it again passing a null name and cashout-address.
+                    
client.patch("/demobanks/default/circuit-api/accounts/exchange-0") {
+                        expectSuccess = true
+                        basicAuth("admin", "foo")
+                        contentType(ContentType.Application.Json)
+                        setBody("{ \"contact_data\": {} }")
+                    }
+                    // PATCH the password.
+                    
client.patch("/demobanks/default/circuit-api/accounts/exchange-0/auth") {
+                        expectSuccess = true
+                        basicAuth("admin", "foo")
+                        contentType(ContentType.Application.Json)
+                        setBody("{ \"new_password\": \"secret\" }")
+                    }
+                    // Check that PATCHing worked.
+                    
client.get("/demobanks/default/access-api/accounts/exchange-0") {
+                        expectSuccess = true
+                        basicAuth("exchange-0", "secret")
+                        contentType(ContentType.Application.Json)
+                    }
+                    // Deleting the account.
+                    
client.delete("/demobanks/default/circuit-api/accounts/exchange-0") {
+                        expectSuccess = true
+                        basicAuth("admin", "foo")
+                    }
+                    // Checking actual deletion.
+                    val R = 
client.get("/demobanks/default/circuit-api/accounts/exchange-0") {
+                        expectSuccess = false
+                        basicAuth("admin", "foo")
+                    }
+                    assert(R.status.value == HttpStatusCode.NotFound.value)
+                }
+            }
+        }
+    }
     // Get /config, fails if != 200.
     @Test
     fun config() {
diff --git a/nexus/src/test/kotlin/SandboxLegacyApiTest.kt 
b/nexus/src/test/kotlin/SandboxLegacyApiTest.kt
index bd8b0248..76ee405d 100644
--- a/nexus/src/test/kotlin/SandboxLegacyApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxLegacyApiTest.kt
@@ -111,7 +111,6 @@ class SandboxLegacyApiTest {
                         val label = "baz"
                     })
                     client.post("/admin/ebics/bank-accounts") {
-                        expectSuccess = true
                         expectSuccess = true
                         contentType(ContentType.Application.Json)
                         basicAuth("admin", "foo")
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
index d9008fb6..d63dac33 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
@@ -6,6 +6,8 @@ import io.ktor.http.*
 import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.SqlExpressionBuilder.like
 import org.jetbrains.exposed.sql.transactions.transaction
 import tech.libeufin.sandbox.CashoutOperationsTable.uuid
 import tech.libeufin.util.*
@@ -79,7 +81,7 @@ data class CircuitContactData(
 
 data class CircuitAccountReconfiguration(
     val contact_data: CircuitContactData,
-    val cashout_address: String,
+    val cashout_address: String?,
     val name: String? = null
 )
 
@@ -96,7 +98,7 @@ data class CircuitAccountInfo(
     val iban: String,
     val contact_data: CircuitContactData,
     val name: String,
-    val cashout_address: String
+    val cashout_address: String?
 )
 
 data class CashoutOperationInfo(
@@ -631,11 +633,12 @@ fun circuitApi(circuitRoute: Route) {
          * that the customer was indeed added via the Circuit API, as opposed
          * to the Access API.
          */
-        val maybeError = "$resourceName not managed by the Circuit API."
         call.respond(CircuitAccountInfo(
             username = customer.username,
-            name = customer.name ?: throw notFound(maybeError),
-            cashout_address = customer.cashout_address ?: throw 
notFound(maybeError),
+            name = customer.name ?: throw internalServerError(
+                "Account '$resourceName' was found without owner's name."
+            ),
+            cashout_address = customer.cashout_address,
             contact_data = CircuitContactData(
                 email = customer.email,
                 phone = customer.phone
@@ -659,10 +662,22 @@ fun circuitApi(circuitRoute: Route) {
         val customers = mutableListOf<Any>()
         val demobank = ensureDemobank(call)
         transaction {
-            DemobankCustomerEntity.find{
-                // like() is case insensitive.
-                DemobankCustomersTable.name.like(filter)
-            }.forEach {
+            /**
+             * This block builds the DB query so that IF the %-wildcard was
+             * given, then BOTH name and name-less accounts are returned.
+             */
+            val query: Op<Boolean> = SqlExpressionBuilder.run {
+                val like = DemobankCustomersTable.name.like(filter)
+                /**
+                 * This IF statement is needed because Postgres would NOT
+                 * match a null column even with the %-wildcard.
+                 */
+                if (filter == "%") {
+                    return@run like.or(DemobankCustomersTable.name.isNull())
+                }
+                return@run like
+            }
+            DemobankCustomerEntity.find { query }.forEach {
                 customers.add(object {
                     val username = it.username
                     val name = it.name
@@ -676,6 +691,7 @@ fun circuitApi(circuitRoute: Route) {
                     )
                 })
             }
+            StdOutSqlLogger
         }
         if (customers.size == 0) {
             call.respond(HttpStatusCode.NoContent)
@@ -727,7 +743,7 @@ fun circuitApi(circuitRoute: Route) {
             throw badRequest("Invalid e-mail address: 
${req.contact_data.email}")
         if ((req.contact_data.phone != null) && 
(!checkPhoneNumber(req.contact_data.phone)))
             throw badRequest("Invalid phone number: ${req.contact_data.phone}")
-        try { parsePayto(req.cashout_address) }
+        try { if (req.cashout_address != null) parsePayto(req.cashout_address) 
}
         catch (e: InvalidPaytoError) {
             throw badRequest("Invalid cash-out address: 
${req.cashout_address}")
         }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 5d492914..54519bbb 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -80,7 +80,7 @@ data class AccountPair(
 )
 fun insertNewAccount(username: String,
                      password: String,
-                     name: String? = null, // tests do not usually give one.
+                     name: String? = null, // tests and access API may not 
give one.
                      iban: String? = null,
                      demobank: String = "default",
                      isPublic: Boolean = false): AccountPair {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
index 2ebe5fc2..e6559897 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/bankAccount.kt
@@ -111,7 +111,19 @@ fun getBalance(accountLabel: String,
         HttpStatusCode.InternalServerError,
         "Demobank '$demobankName' not found"
     )
-    val account = getBankAccountFromLabel(accountLabel, demobank)
+
+    /**
+     * Setting withBankFault to true for the following reason:
+     * when asking for a balance, the bank should have made sure
+     * that the user has a bank account (together with a customer profile).
+     * If that's not the case, it's bank's fault, since it didn't check
+     * earlier.
+     */
+    val account = getBankAccountFromLabel(
+        accountLabel,
+        demobank,
+        withBankFault = true
+    )
     return getBalance(account, withPending)
 }
 

-- 
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]