gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated (49469ce -> 2cd810f)


From: gnunet
Subject: [libeufin] branch master updated (49469ce -> 2cd810f)
Date: Wed, 13 Jan 2021 22:13:52 +0100

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

dold pushed a change to branch master
in repository libeufin.

    from 49469ce  remove deprecated endpoint
     new 91d31e4  install sandbox by default
     new 2cd810f  implement per-account transaction listing in sandbox

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Makefile                                           |   2 +-
 cli/bin/libeufin-cli                               |  65 +++++++++-
 .../src/main/kotlin/tech/libeufin/sandbox/DB.kt    |   4 +-
 .../main/kotlin/tech/libeufin/sandbox/Helpers.kt   |  11 ++
 .../src/main/kotlin/tech/libeufin/sandbox/JSON.kt  |   3 +-
 .../src/main/kotlin/tech/libeufin/sandbox/Main.kt  | 137 ++++++++++++++++++++-
 6 files changed, 211 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index 24425c1..571d75a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ include build-system/config.mk
 
 escaped_pwd = $(shell pwd | sed 's/\//\\\//g')
 
-install: install-nexus install-cli
+install: install-nexus install-sandbox install-cli
 install-dev: install-nexus-dev install-sandbox-dev install-cli
 
 .PHONY: dist
diff --git a/cli/bin/libeufin-cli b/cli/bin/libeufin-cli
index ed79436..803a60a 100755
--- a/cli/bin/libeufin-cli
+++ b/cli/bin/libeufin-cli
@@ -334,9 +334,9 @@ def show(obj):
     print(resp.content.decode("utf-8"))
 
 @accounts.command(help="prepare payment debiting 'account-name'")
-@click.option("--credit-iban", help="IBAN that will receive the payment", 
required=True)
-@click.option("--credit-bic", help="BIC that will receive the payment", 
required=False)
-@click.option("--credit-name", help="Legal name that will receive the 
payment", required=True)
+@click.option("--creditor-iban", help="IBAN that will receive the payment", 
required=True)
+@click.option("--creditor-bic", help="BIC that will receive the payment", 
required=False)
+@click.option("--creditor-name", help="Legal name that will receive the 
payment", required=True)
 @click.option("--payment-amount", help="Amount to be paid (<currency>:X.Y)", 
required=True)
 @click.option("--payment-subject", help="Subject of this payment", 
required=True)
 @click.argument("account-name")
@@ -448,18 +448,30 @@ def new_facade(obj, facade_name, connection_name, 
account_name):
     print(resp.content.decode("utf-8"))
 
 
-
 @sandbox.group("ebicshost", help="manage EBICS hosts")
 @click.pass_context
 def sandbox_ebicshost(ctx):
     pass
 
+@sandbox.command("check", help="check sandbox status")
+@click.pass_obj
+def check_sandbox_status(obj):
+    sandbox_base_url = obj.require_sandbox_base_url()
+    url = urljoin(sandbox_base_url, "/config")
+    try:
+        resp = get(url)
+    except Exception:
+        print("Could not reach sandbox")
+        exit(1)
+    print(resp.content.decode("utf-8"))
+
+
 @sandbox_ebicshost.command("create", help="Create an EBICS host")
 @click.option("--host-id", help="EBICS host ID", required=True, prompt=True)
 @click.pass_obj
 def make_ebics_host(obj, host_id):
     sandbox_base_url = obj.require_sandbox_base_url()
-    url = urljoin(sandbox_base_url, "/admin/ebics/host")
+    url = urljoin(sandbox_base_url, "/admin/ebics/hosts")
     try:
         resp = post(url, json=dict(hostID=host_id, ebicsVersion="2.5"))
     except Exception:
@@ -517,6 +529,7 @@ def sandbox_ebicsbankaccount(ctx):
     pass
 
 @sandbox_ebicsbankaccount.command("create", help="Create a bank account 
associated to an EBICS subscriber.")
+@click.option("--currency", help="currency", prompt=True)
 @click.option("--iban", help="IBAN", required=True)
 @click.option("--bic", help="BIC", required=True)
 @click.option("--person-name", help="bank account owner name", required=True)
@@ -525,11 +538,12 @@ def sandbox_ebicsbankaccount(ctx):
 @click.option("--ebics-host-id", help="host ID of the Ebics subscriber", 
required=True)
 @click.option("--ebics-partner-id", help="partner ID of the Ebics subscriber", 
required=True)
 @click.pass_obj
-def associate_bank_account(obj, iban, bic, person_name, account_name,
+def associate_bank_account(obj, currency, iban, bic, person_name, account_name,
                            ebics_user_id, ebics_host_id, ebics_partner_id):
     sandbox_base_url = obj.require_sandbox_base_url()
     url = urljoin(sandbox_base_url, "/admin/ebics/bank-accounts")
     body = dict(
+        currency=currency,
         subscriber=dict(userID=ebics_user_id, partnerID=ebics_partner_id, 
hostID=ebics_host_id),
         iban=iban, bic=bic, name=person_name, label=account_name
     )
@@ -546,6 +560,45 @@ def associate_bank_account(obj, iban, bic, person_name, 
account_name,
 def sandbox_bankaccount(ctx):
     pass
 
+@sandbox_bankaccount.command("list", help="List accounts")
+@click.pass_obj
+def bankaccount_list(obj):
+    sandbox_base_url = obj.require_sandbox_base_url()
+    url = urljoin(sandbox_base_url, f"/admin/bank-accounts")
+    try:
+        resp = get(url)
+    except Exception:
+        print("Could not reach sandbox")
+        exit(1)
+    print(resp.content.decode("utf-8"))
+
+@sandbox_bankaccount.command("transactions", help="List transactions")
+@click.argument("account-label")
+@click.pass_obj
+def bankaccount_list(obj, account_label):
+    sandbox_base_url = obj.require_sandbox_base_url()
+    url = urljoin(sandbox_base_url, 
f"/admin/bank-accounts/{account_label}/transactions")
+    try:
+        resp = get(url)
+    except Exception:
+        print("Could not reach sandbox")
+        exit(1)
+    print(resp.content.decode("utf-8"))
+
+@sandbox_bankaccount.command("generate-transactions", help="Generate test 
transactions")
+@click.argument("account-label")
+@click.pass_obj
+def bankaccount_generate_transactions(obj, account_label):
+    sandbox_base_url = obj.require_sandbox_base_url()
+    url = urljoin(sandbox_base_url, 
f"/admin/bank-accounts/{account_label}/generate-transactions")
+    try:
+        resp = post(url)
+    except Exception:
+        print("Could not reach sandbox")
+        exit(1)
+    print(resp.content.decode("utf-8"))
+
+
 @sandbox_bankaccount.command(help="book a payment in the sandbox")
 @click.option("--creditor-iban", help="IBAN receiving the payment", 
prompt=True)
 @click.option("--creditor-bic", help="BIC receiving the payment", prompt=True)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
index 82124f9..9ea9a0e 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -273,8 +273,9 @@ object BankAccountsTable : IntIdTable() {
     val iban = text("iban")
     val bic = text("bic")
     val name = text("name")
-    val label = text("label")
+    val label = text("label").uniqueIndex("accountLabelIndex")
     val subscriber = reference("subscriber", EbicsSubscribersTable)
+    val currency = text("currency")
 }
 
 class BankAccountEntity(id: EntityID<Int>) : IntEntity(id) {
@@ -285,6 +286,7 @@ class BankAccountEntity(id: EntityID<Int>) : IntEntity(id) {
     var name by BankAccountsTable.name
     var label by BankAccountsTable.label
     var subscriber by EbicsSubscriberEntity referencedOn 
BankAccountsTable.subscriber
+    var currency by BankAccountsTable.currency
 }
 
 object BankAccountStatementsTable : IntIdTable() {
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 0ea1927..bc9c908 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -53,6 +53,17 @@ fun getBankAccountFromIban(iban: String): BankAccountEntity {
     )
 }
 
+fun getBankAccountFromLabel(label: String): BankAccountEntity {
+    return transaction {
+        BankAccountEntity.find(
+            BankAccountsTable.label eq label
+        )
+    }.firstOrNull() ?: throw SandboxError(
+        HttpStatusCode.NotFound,
+        "Did not find a bank account for label ${label}"
+    )
+}
+
 fun getBankAccountFromSubscriber(subscriber: EbicsSubscriberEntity): 
BankAccountEntity {
     return transaction {
         BankAccountEntity.find(BankAccountsTable.subscriber eq subscriber.id)
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
index ad46123..69804e7 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
@@ -69,7 +69,8 @@ data class BankAccountRequest(
     val iban: String,
     val bic: String,
     val name: String,
-    val label: String
+    val label: String,
+    val currency: String
 )
 
 data class DateRange(
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt 
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 7152169..404ac70 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -77,6 +77,7 @@ import 
tech.libeufin.sandbox.BankAccountTransactionsTable.direction
 import tech.libeufin.util.*
 import tech.libeufin.util.ebics_h004.EbicsResponse
 import tech.libeufin.util.ebics_h004.EbicsTypes
+import java.util.*
 import kotlin.random.Random
 
 const val DEFAULT_DB_CONNECTION = "jdbc:sqlite:/tmp/libeufin-sandbox.sqlite3"
@@ -86,6 +87,7 @@ class BadInputData(inputData: String?) : Exception("Customer 
provided invalid in
 class UnacceptableFractional(badNumber: BigDecimal) : Exception(
     "Unacceptable fractional part ${badNumber}"
 )
+
 lateinit var LOGGER: Logger
 
 data class SandboxError(val statusCode: HttpStatusCode, val reason: String) : 
Exception()
@@ -102,6 +104,7 @@ class ResetTables : CliktCommand("Drop all the tables from 
the database") {
             helpFormatter = CliktHelpFormatter(showDefaultValues = true)
         }
     }
+
     private val dbConnString by option().default(DEFAULT_DB_CONNECTION)
     override fun run() {
         execThrowableOrTerminate {
@@ -117,6 +120,7 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
             helpFormatter = CliktHelpFormatter(showDefaultValues = true)
         }
     }
+
     private val dbConnString by option().default(DEFAULT_DB_CONNECTION)
     private val logLevel by option()
     private val port by option().int().default(5000)
@@ -160,6 +164,17 @@ data class EbicsHostPublicInfo(
     val authenticationPublicKey: RSAPublicKey
 )
 
+data class BankAccountInfo(
+    val label: String,
+    val name: String,
+    val iban: String,
+    val bic: String
+)
+
+data class BankAccountsListReponse(
+    val accounts: List<BankAccountInfo>
+)
+
 inline fun <reified T> Document.toObject(): T {
     val jc = JAXBContext.newInstance(T::class.java)
     val m = jc.createUnmarshaller()
@@ -171,6 +186,12 @@ fun BigDecimal.signToString(): String {
     // minus sign is added by default already.
 }
 
+fun ensureNonNull(param: String?): String {
+    return param ?: throw SandboxError(
+        HttpStatusCode.BadRequest, "Bad ID given: $param"
+    )
+}
+
 fun main(args: Array<String>) {
     SandboxCommand()
         .subcommands(Serve(), ResetTables())
@@ -259,6 +280,14 @@ fun serverMain(dbName: String, port: Int) {
             get("/") {
                 call.respondText("Hello, this is Sandbox\n", 
ContentType.Text.Plain)
             }
+            get("/config") {
+                call.respond(object {
+                    val name = "libeufin-sandbox"
+
+                    // FIXME: use actual version here!
+                    val version = "0.0.0-dev.0"
+                })
+            }
             // only reason for a post is to hide the iban (to some degree.)
             post("/admin/payments/camt") {
                 val body = call.receive<CamtParams>()
@@ -268,6 +297,7 @@ fun serverMain(dbName: String, port: Int) {
                 call.respondText(camt53, ContentType.Text.Xml, 
HttpStatusCode.OK)
                 return@post
             }
+            // FIXME:  This returns *all* payments for all accounts.  Is that 
really useful/required?
             get("/admin/payments") {
                 val ret = PaymentsResponse()
                 transaction {
@@ -342,11 +372,114 @@ fun serverMain(dbName: String, port: Int) {
                         bic = body.bic
                         name = body.name
                         label = body.label
+                        currency = body.currency.toUpperCase(Locale.ROOT)
                     }
                 }
                 call.respondText("Bank account created")
                 return@post
             }
+            get("/admin/bank-accounts") {
+                val accounts = mutableListOf<BankAccountInfo>()
+                val accountsResp = BankAccountsListReponse(
+                    accounts = accounts
+                )
+                transaction {
+                    BankAccountEntity.all().forEach {
+                        accounts.add(
+                            BankAccountInfo(
+                                label = it.label,
+                                name = it.name,
+                                bic = it.bic,
+                                iban = it.iban
+                            )
+                        )
+                    }
+                }
+                call.respond(accounts)
+            }
+            get("/admin/bank-accounts/{label}/transactions") {
+                val ret = PaymentsResponse()
+                transaction {
+                    val accountLabel = ensureNonNull(call.parameters["label"])
+                    transaction {
+                        val account = getBankAccountFromLabel(accountLabel)
+                        BankAccountTransactionsTable.select { 
BankAccountTransactionsTable.account eq account.id }
+                            .forEach {
+                                ret.payments.add(
+                                    RawPayment(
+                                        creditorIban = it[creditorIban],
+                                        debitorIban = it[debitorIban],
+                                        subject = 
it[BankAccountTransactionsTable.subject],
+                                        date = it[date].toHttpDateString(),
+                                        amount = it[amount],
+                                        creditorBic = it[creditorBic],
+                                        creditorName = it[creditorName],
+                                        debitorBic = it[debitorBic],
+                                        debitorName = it[debitorName],
+                                        currency = it[currency],
+                                        direction = it[direction]
+                                    )
+                                )
+                            }
+                    }
+                }
+                call.respond(
+                    object {
+                        val payments = ret
+                    }
+                )
+            }
+            post("/admin/bank-accounts/{label}/generate-transactions") {
+                transaction {
+                    val accountLabel = ensureNonNull(call.parameters["label"])
+                    val account = getBankAccountFromLabel(accountLabel)
+
+                    run {
+                        val random = Random.nextLong()
+                        val amount = Random.nextLong(5, 25)
+
+                        BankAccountTransactionsTable.insert {
+                            it[creditorIban] = account.iban
+                            it[creditorBic] = account.bic
+                            it[creditorName] = account.name
+                            it[debitorIban] = "DE64500105178797276788"
+                            it[debitorBic] = "FOBADEM001"
+                            it[debitorName] = "Max Mustermann"
+                            it[subject] = "sample transaction $random"
+                            it[BankAccountTransactionsTable.amount] = 
amount.toString()
+                            it[currency] = account.currency
+                            it[date] = Instant.now().toEpochMilli()
+                            it[pmtInfId] = random.toString()
+                            it[msgId] = random.toString()
+                            it[BankAccountTransactionsTable.account] = 
account.id
+                            it[direction] = "CRDT"
+                        }
+                    }
+
+                    run {
+                        val random = Random.nextLong()
+                        val amount = Random.nextLong(5, 25)
+
+                        BankAccountTransactionsTable.insert {
+                            it[debitorIban] = account.iban
+                            it[debitorBic] = account.bic
+                            it[debitorName] = account.name
+                            it[creditorIban] = "DE64500105178797276788"
+                            it[creditorBic] = "FOBADEM001"
+                            it[creditorName] = "Max Mustermann"
+                            it[subject] = "sample transaction $random"
+                            it[BankAccountTransactionsTable.amount] = 
amount.toString()
+                            it[currency] = account.currency
+                            it[date] = Instant.now().toEpochMilli()
+                            it[pmtInfId] = random.toString()
+                            it[msgId] = random.toString()
+                            it[BankAccountTransactionsTable.account] = 
account.id
+                            it[direction] = "DBIT"
+                        }
+                    }
+                }
+                call.respond(object {})
+            }
             /**
              * Creates a new Ebics subscriber.
              */
@@ -372,7 +505,7 @@ fun serverMain(dbName: String, port: Int) {
              * Shows all the Ebics subscribers' details.
              */
             get("/admin/ebics/subscribers") {
-                var ret = AdminGetSubscribers()
+                val ret = AdminGetSubscribers()
                 transaction {
                     EbicsSubscriberEntity.all().forEach {
                         ret.subscribers.add(
@@ -431,4 +564,4 @@ fun serverMain(dbName: String, port: Int) {
     }
     LOGGER.info("Up and running")
     server.start(wait = true)
-}
+}
\ 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]