[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.
- [libeufin] branch master updated (49469ce -> 2cd810f),
gnunet <=