libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 1affba91610fb88f8ccb782ec9cb430cba7f361f
parent c58a867f3e0a32f5bfa7cfa1e40ad02cbfa1907d
Author: MS <ms@taler.net>
Date:   Tue,  3 Oct 2023 10:37:36 +0200

GET /public-accounts, DB level

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/BankMessages.kt | 14++++++++++++++
Mbank/src/main/kotlin/tech/libeufin/bank/CorebankApiHandlers.kt | 5++++-
Mbank/src/main/kotlin/tech/libeufin/bank/Database.kt | 45+++++++++++++++++++++++++++++++++++++++++++++
Mbank/src/test/kotlin/DatabaseTest.kt | 34+++++++++++++++++++++++++++++++++-
4 files changed, 96 insertions(+), 2 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankMessages.kt b/bank/src/main/kotlin/tech/libeufin/bank/BankMessages.kt @@ -648,4 +648,18 @@ data class TransferRequest( data class TransferResponse( val timestamp: TalerProtocolTimestamp, val row_id: Long +) + +/** + * Response to GET /public-accounts + */ +@Serializable +data class PublicAccountsResponse( + val public_accounts: MutableList<PublicAccount> +) +@Serializable +data class PublicAccount( + val payto_uri: String, + val balance: Balance, + val account_name: String ) \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CorebankApiHandlers.kt b/bank/src/main/kotlin/tech/libeufin/bank/CorebankApiHandlers.kt @@ -220,7 +220,10 @@ fun Routing.accountsMgmtHandlers(db: Database, ctx: BankApplicationContext) { call.respond(HttpStatusCode.Created) return@post } - + get("/public-accounts") { + // no authentication here. + // val publicAccounts = db.accountsGetPublic() + } get("/accounts") { val c = call.authenticateBankRequest(db, TokenScope.readonly) ?: throw unauthorized() if (c.login != "admin") throw forbidden("Only admin allowed.") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt @@ -398,6 +398,51 @@ class Database(private val dbConfig: String, private val bankCurrency: String) { } // MIXED CUSTOMER AND BANK ACCOUNT DATA + /** + * Gets the list of public accounts in the system. + * internalCurrency is the bank's currency and loginFilter is + * an optional filter on the account's login. + * + * Returns an empty list, if no public account was found. + */ + fun accountsGetPublic(internalCurrency: String, loginFilter: String = "%"): List<PublicAccount> { + reconnect() + val stmt = prepare(""" + SELECT + (balance).val AS balance_val, + (balance).frac AS balance_frac, + has_debt, + internal_payto_uri, + c.login + FROM bank_accounts JOIN customers AS c + ON owning_customer_id = c.customer_id + WHERE is_public=true AND c.login LIKE ?; + """) + stmt.setString(1, loginFilter) + val res = stmt.executeQuery() + val ret = mutableListOf<PublicAccount>() + res.use { + if (!it.next()) return ret + do { + ret.add(PublicAccount( + account_name = it.getString("login"), + payto_uri = it.getString("internal_payto_uri"), + balance = Balance( + amount = TalerAmount( + value = it.getLong("balance_val"), + frac = it.getInt("balance_frac"), + currency = internalCurrency + ), + credit_debit_indicator = it.getBoolean("has_debt").run { + if (this) return@run CorebankCreditDebitInfo.debit + return@run CorebankCreditDebitInfo.credit + } + ) + )) + } while (it.next()) + } + return ret + } /** * Gets a minimal set of account data, as outlined in the GET /accounts diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt @@ -413,7 +413,7 @@ class DatabaseTest { // Tests the retrieval of many accounts, used along GET /accounts @Test - fun accountsForAdmin() { + fun accountsForAdminTest() { val db = initDb() assert(db.accountsGetForAdmin().isEmpty()) // No data exists yet. assert(db.customerCreate(customerFoo) != null) @@ -424,4 +424,36 @@ class DatabaseTest { assert(db.accountsGetForAdmin("F%").size == 1) // gets Foo only assert(db.accountsGetForAdmin("%ar").size == 1) // gets Bar only } + + @Test + fun getPublicAccountsTest() { + val db = initDb() + // Expecting empty, no accounts exist yet. + assert(db.accountsGetPublic("KUDOS").isEmpty()) + // Make a NON-public account, so expecting still an empty result. + assert(db.customerCreate(customerFoo) != null) + assert(db.bankAccountCreate(bankAccountFoo) != null) + assert(db.accountsGetPublic("KUDOS").isEmpty()) + + // Make a public account, so expecting one result. + db.customerCreate(customerBar).apply { + assert(this != null) + assert(db.bankAccountCreate( + BankAccount( + isPublic = true, + internalPaytoUri = "payto://iban/non-used", + lastNexusFetchRowId = 1L, + owningCustomerId = this!!, + hasDebt = false, + maxDebt = TalerAmount(10, 1, "KUDOS") + ) + ) != null) + } + assert(db.accountsGetPublic("KUDOS").size == 1) + + // Same expectation, filtering on the login "bar" + assert(db.accountsGetPublic("KUDOS", "b%").size == 1) + // Expecting empty, as the filter should match nothing. + assert(db.accountsGetPublic("KUDOS", "x").isEmpty()) + } }