gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: circuit API


From: gnunet
Subject: [libeufin] branch master updated: circuit API
Date: Thu, 09 Feb 2023 17:34:44 +0100

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 09aed8c3 circuit API
09aed8c3 is described below

commit 09aed8c3210acb636cd09b8babe55dc3a99e7b42
Author: MS <ms@taler.net>
AuthorDate: Thu Feb 9 17:34:02 2023 +0100

    circuit API
    
    allowing a filter over the cash-out author
---
 nexus/src/test/kotlin/MakeEnv.kt                   |  1 +
 nexus/src/test/kotlin/SandboxCircuitApiTest.kt     | 32 +++++++++++++-
 .../kotlin/tech/libeufin/sandbox/CircuitApi.kt     | 51 ++++++++++++++++++----
 3 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/nexus/src/test/kotlin/MakeEnv.kt b/nexus/src/test/kotlin/MakeEnv.kt
index 52e5dd35..269a6380 100644
--- a/nexus/src/test/kotlin/MakeEnv.kt
+++ b/nexus/src/test/kotlin/MakeEnv.kt
@@ -246,6 +246,7 @@ fun prepSandboxDb() {
             username = "bar"
             passwordHash = CryptoUtil.hashpw("bar")
             name = "Bar"
+            cashout_address = "payto://iban/FIAT"
         }
         DemobankCustomerEntity.new {
             username = "baz"
diff --git a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt 
b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
index 31955ff4..decadf3b 100644
--- a/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxCircuitApiTest.kt
@@ -26,6 +26,24 @@ class SandboxCircuitApiTest {
         }
     }
 
+    @Test
+    fun accessAccountsTest() {
+        withTestDatabase {
+            prepSandboxDb()
+            testApplication {
+                application(sandboxApp)
+                val R = 
client.get("/demobanks/default/circuit-api/accounts/bar") {
+                    basicAuth("foo", "foo")
+                    expectSuccess = false
+                }
+                assert(R.status.value == HttpStatusCode.Forbidden.value)
+                client.get("/demobanks/default/circuit-api/accounts/bar") {
+                    basicAuth("admin", "foo")
+                    expectSuccess = true
+                }
+            }
+        }
+    }
     // Only tests that the calls get a 2xx status code.
     @Test
     fun listAccountsTest() {
@@ -96,7 +114,7 @@ class SandboxCircuitApiTest {
                         subject = "unused"
                         creationTime = 0L
                         tanChannel = SupportedTanChannels.FILE // change type 
to enum?
-                        account = "unused"
+                        account = "foo"
                         status = CashoutOperationStatus.PENDING
                     }
                 }
@@ -118,6 +136,18 @@ class SandboxCircuitApiTest {
                 val status = respJson.get("status").asText()
                 assert(status.uppercase() == "PENDING")
                 println(R.bodyAsText())
+                // Check that bar doesn't get foo's cash-out
+                R = 
client.get("/demobanks/default/circuit-api/cashouts?account=foo") {
+                    expectSuccess = false
+                    basicAuth("bar", "bar")
+                }
+                assert(R.status.value == HttpStatusCode.Forbidden.value)
+                // Check that foo can get its own
+                R = 
client.get("/demobanks/default/circuit-api/cashouts?account=foo") {
+                    expectSuccess = false
+                    basicAuth("foo", "foo")
+                }
+                assert(R.status.value == HttpStatusCode.OK.value)
             }
         }
     }
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
index 992346a1..a21820a6 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/CircuitApi.kt
@@ -290,14 +290,43 @@ fun circuitApi(circuitRoute: Route) {
         call.respond(ret)
         return@get
     }
-    // Gets the list of all the cash-out operations.
+    // Gets the list of all the cash-out operations,
+    // or those belonging to the account given as a parameter.
     circuitRoute.get("/cashouts") {
-        call.request.basicAuth(onlyAdmin = true)
+        val user = call.request.basicAuth()
+        val whichAccount = call.request.queryParameters["account"]
+        /**
+         * Only admin's allowed to omit the target account (= get
+         * all the accounts) or to check other customers cash-out
+         * operations.
+         */
+        if (user != "admin" && whichAccount != user) throw forbidden(
+            "Ordinary users can only request their own account"
+        )
+        /**
+         * At this point, the client has the rights over the account(s)
+         * whose operations are to be returned.  Double-checking that
+         * Admin doesn't ask its own cash-outs, since that's not supported.
+         */
+        if (whichAccount == "admin") throw badRequest("Cash-out for admin is 
not supported")
+
+        // Preparing the response.
         val node = jacksonObjectMapper().createObjectNode()
         val maybeArray = node.putArray("cashouts")
-        transaction {
-            CashoutOperationEntity.all().forEach {
-                maybeArray.add(it.uuid.toString())
+
+        if (whichAccount == null) { // no target account, return all the 
cash-outs
+            transaction {
+                CashoutOperationEntity.all().forEach {
+                    maybeArray.add(it.uuid.toString())
+                }
+            }
+        } else { // do filter on the target account.
+            transaction {
+                CashoutOperationEntity.find {
+                    CashoutOperationsTable.account eq whichAccount
+                }.forEach {
+                    maybeArray.add(it.uuid.toString())
+                }
             }
         }
         if (maybeArray.size() == 0) {
@@ -445,7 +474,9 @@ fun circuitApi(circuitRoute: Route) {
         val username = call.request.basicAuth()
         val resourceName = call.getUriComponent("resourceName")
         throwIfInstitutionalName(resourceName)
-        allowOwnerOrAdmin(username, resourceName)
+        if (!allowOwnerOrAdmin(username, resourceName)) throw forbidden(
+            "User $username has no rights over $resourceName"
+        )
         val customer = getCustomer(resourceName)
         /**
          * CUSTOMER AND BANK ACCOUNT INVARIANT.
@@ -506,7 +537,9 @@ fun circuitApi(circuitRoute: Route) {
         val username = call.request.basicAuth()
         val customerUsername = call.getUriComponent("customerUsername")
         throwIfInstitutionalName(customerUsername)
-        allowOwnerOrAdmin(username, customerUsername)
+        if (!allowOwnerOrAdmin(username, customerUsername)) throw forbidden(
+            "User $username has no rights over $customerUsername"
+        )
         // Flow here means admin or username have the rights for this 
operation.
         val req = call.receive<AccountPasswordChange>()
         /**
@@ -528,7 +561,9 @@ fun circuitApi(circuitRoute: Route) {
             throw internalServerError("Authentication disabled, don't have a 
default for this request.")
         val resourceName = call.getUriComponent("resourceName")
         throwIfInstitutionalName(resourceName)
-        allowOwnerOrAdmin(username, resourceName)
+        if(!allowOwnerOrAdmin(username, resourceName)) throw forbidden(
+            "User $username has no rights over $resourceName"
+        )
         // account found and authentication succeeded
         val req = call.receive<CircuitAccountReconfiguration>()
         // Only admin's allowed to change the legal name

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