gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: time ranged history (access API)


From: gnunet
Subject: [libeufin] branch master updated: time ranged history (access API)
Date: Wed, 22 Mar 2023 16:23:52 +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 4887d87c time ranged history (access API)
4887d87c is described below

commit 4887d87c0be652b21fcf6f2c6d6dde2b05dd4a66
Author: ms <ms@taler.net>
AuthorDate: Wed Mar 22 16:23:29 2023 +0100

    time ranged history (access API)
---
 nexus/src/test/kotlin/SandboxAccessApiTest.kt      | 73 ++++++++++++++++++++++
 .../src/main/kotlin/tech/libeufin/sandbox/Main.kt  | 29 +++++----
 util/src/main/kotlin/HTTP.kt                       | 15 +++++
 3 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/nexus/src/test/kotlin/SandboxAccessApiTest.kt 
b/nexus/src/test/kotlin/SandboxAccessApiTest.kt
index b5182bd1..4c0232c9 100644
--- a/nexus/src/test/kotlin/SandboxAccessApiTest.kt
+++ b/nexus/src/test/kotlin/SandboxAccessApiTest.kt
@@ -1,3 +1,4 @@
+import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.ObjectMapper
 import io.ktor.client.plugins.*
 import io.ktor.client.request.*
@@ -63,6 +64,78 @@ class SandboxAccessApiTest {
         }
     }
 
+    // Tests the time range filter of Access API's GET /transactions
+    @Test
+    fun timeRangedTransactions() {
+        fun getTxs(respJson: String): JsonNode {
+            val mapper = ObjectMapper()
+            return mapper.readTree(respJson).get("transactions")
+        }
+        withTestDatabase {
+            prepSandboxDb()
+            testApplication {
+                application(sandboxApp)
+                var R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions") {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 0) // Checking that no 
transactions exist.
+                wireTransfer(
+                    "admin",
+                    "foo",
+                    "default",
+                    "#0",
+                    "TESTKUDOS:2"
+                )
+                R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions") {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 1) // Checking that #0 
shows up.
+                // Asking up to a point in the past, where no txs should exist.
+                R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions?until_ms=3000")
 {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 0) // Not expecting 
any transaction.
+                // Moving the transaction back in the past
+                transaction {
+                    val tx_0 = BankAccountTransactionEntity.find {
+                        BankAccountTransactionsTable.subject eq "#0" and
+                                (BankAccountTransactionsTable.direction eq 
"CRDT")
+                    }.first()
+                    tx_0.date = 10000
+                }
+                // Picking the past transaction from one including time range,
+                // therefore expecting one entry in the result
+                R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions?from_ms=9000&until_ms=11000")
 {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 1)
+                // Not enough txs to fill the second page, expecting no txs 
therefore.
+                R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions?page=2&size=1")
 {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 0)
+                // Creating one more tx and asking the second 1-sized page, 
expecting therefore one result.
+                wireTransfer(
+                    "admin",
+                    "foo",
+                    "default",
+                    "#1",
+                    "TESTKUDOS:2"
+                )
+                R = 
client.get("/demobanks/default/access-api/accounts/foo/transactions?page=2&size=1")
 {
+                    expectSuccess = true
+                    basicAuth("foo", "foo")
+                }
+                assert(getTxs(R.bodyAsText()).size() == 1)
+            }
+        }
+    }
+
     // Tests for #7482
     @Test
     fun highAmountWithdraw() {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 5bceaf6b..4d91257d 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -1482,34 +1482,39 @@ val sandboxApp: Application.() -> Unit = {
                     val authGranted: Boolean = bankAccount.isPublic || 
!WITH_AUTH || username == "admin"
                     if (!authGranted && bankAccount.owner != username)
                         throw forbidden("Cannot access bank account 
${bankAccount.label}")
-                    val page: Int = 
Integer.decode(call.request.queryParameters["page"] ?: "0")
-                    val size: Int = 
Integer.decode(call.request.queryParameters["size"] ?: "5")
-
+                    // Paging values.
+                    val page: Int = 
expectInt(call.request.queryParameters["page"] ?: "1")
+                    val size: Int = 
expectInt(call.request.queryParameters["size"] ?: "5")
+                    // Time range filter values
+                    val fromMs = 
expectLong(call.request.queryParameters["from_ms"] ?: "0")
+                    val untilMs = 
expectLong(call.request.queryParameters["until_ms"] ?: 
Long.MAX_VALUE.toString())
                     val ret = mutableListOf<RawPayment>()
                     /**
                      * Case where page number wasn't given,
-                     * therefore the results starts from the last transaction. 
*/
+                     * therefore the results starts from the last transaction.
+                     */
                     transaction {
                         /**
                          * Get a history page - from the calling bank account 
- having
                          * 'firstElementId' as the latest transaction in it.  
*/
                         fun getPage(firstElementId: Long): 
Iterable<BankAccountTransactionEntity> {
-                            logger.debug("History page from tx 
$firstElementId, including $size txs in the past.")
+                            logger.debug("Trying to build pageBuf from ID: 
$firstElementId," +
+                                    " including $size txs in the past."
+                            )
                             return BankAccountTransactionEntity.find {
                                 (BankAccountTransactionsTable.id lessEq 
firstElementId) and
-                                        (BankAccountTransactionsTable.account 
eq bankAccount.id)
+                                        (BankAccountTransactionsTable.account 
eq bankAccount.id) and
+                                        
(BankAccountTransactionsTable.date.between(fromMs, untilMs))
                             }.sortedByDescending { it.id.value }.take(size)
                         }
                         val lt: BankAccountTransactionEntity? = 
bankAccount.lastTransaction
                         if (lt == null) return@transaction
                         var nextPageIdUpperLimit: Long = lt.id.value
-                        /**
-                         * This loop fetches (and discards) pages until the
-                         * desired one is found.  */
-                        for (i in 0..(page)) {
+                        // This loop fetches (and discards) pages until the 
desired one is found.
+                        for (i in 1..(page)) {
                             val pageBuf = getPage(nextPageIdUpperLimit)
-                            logger.debug("Processing page:")
-                            pageBuf.forEach { logger.debug("${it.id} 
${it.subject} ${it.amount}") }
+                            logger.debug("pageBuf #$i follows.  Request wants 
#$page:")
+                            pageBuf.forEach { logger.debug("ID: ${it.id}, 
subject: ${it.subject}, amount: ${it.currency}:${it.amount}") }
                             if (pageBuf.none()) return@transaction
                             nextPageIdUpperLimit = pageBuf.last().id.value - 1
                             if (i == page) pageBuf.forEach {
diff --git a/util/src/main/kotlin/HTTP.kt b/util/src/main/kotlin/HTTP.kt
index 85e592ab..374bc857 100644
--- a/util/src/main/kotlin/HTTP.kt
+++ b/util/src/main/kotlin/HTTP.kt
@@ -186,3 +186,18 @@ fun extractUserAndPassword(authorizationHeader: String): 
Pair<String, String> {
     }
     return Pair(username, password)
 }
+
+fun expectInt(uriParam: String): Int {
+    return try { Integer.decode(uriParam) }
+    catch (e: Exception) {
+        logger.error(e.message)
+        throw badRequest("'$uriParam' is not Int")
+    }
+}
+fun expectLong(uriParam: String): Long {
+    return try { uriParam.toLong() }
+    catch (e: Exception) {
+        logger.error(e.message)
+        throw badRequest("'$uriParam' is not Long")
+    }
+}
\ No newline at end of file

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