[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: Access API: implement create transacti
From: |
gnunet |
Subject: |
[libeufin] branch master updated: Access API: implement create transactions. |
Date: |
Wed, 01 Dec 2021 10:43:15 +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 4482f8d4 Access API: implement create transactions.
4482f8d4 is described below
commit 4482f8d42bab26a787e154a3466be03d5d51d3b5
Author: ms <ms@taler.net>
AuthorDate: Wed Dec 1 10:42:41 2021 +0100
Access API: implement create transactions.
---
cli/bin/libeufin-cli | 43 +++++++++++++++++++-
.../main/kotlin/tech/libeufin/sandbox/Helpers.kt | 46 +++++++++++++++++-----
.../src/main/kotlin/tech/libeufin/sandbox/JSON.kt | 10 +++++
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 31 ++++++++++++++-
4 files changed, 118 insertions(+), 12 deletions(-)
diff --git a/cli/bin/libeufin-cli b/cli/bin/libeufin-cli
index d264b5ac..f7333aaa 100755
--- a/cli/bin/libeufin-cli
+++ b/cli/bin/libeufin-cli
@@ -1187,11 +1187,52 @@ def sandbox_bankaccount(ctx):
# This group deals with the new Access API
# and the 'demobank' model.
-@sandbox.group("demobank", help="manage customers")
+@sandbox.group(
+ "demobank",
+ help="Subcommands for the 'demobank' model and the Access API."
+)
@click.pass_context
def sandbox_demobank(ctx):
pass
+@sandbox_demobank.command("new-transaction", help="Initiate a new
transaction.")
+@click.option(
+ "--bank-account",
+ help="Label of the bank account to be debited for the transaction.",
+ required=True
+)
+# Including the subject in the payto to match the
+# payto returned by the merchant backend helper program
+# to create tip reserves.
+@click.option(
+ "--payto-with-subject",
+ help="Payto address including the subject as a query parameter.",
+ required=True
+)
+@click.option(
+ "--amount",
+ help="Amount to transfer, in the $currency:X.Y format.",
+ required=True
+)
+@click.pass_obj
+def sandbox_demobank_new_transaction(obj, bank_account, payto_with_subject,
amount):
+ # expected to include the demobank name.
+ sandbox_base_url = obj.require_sandbox_base_url()
+ url = urljoin_nodrop(sandbox_base_url,
f"/access-api/accounts/{bank_account}/transactions")
+ try:
+ body = dict(paytoUri=payto_with_subject, amount=amount)
+ resp = post(
+ url,
+ json=body,
+ auth=auth.HTTPBasicAuth(obj.username, obj.password),
+ )
+ except Exception as e:
+ print(e)
+ print("Could not reach Sandbox at " + url)
+ exit(1)
+
+ check_response_status(resp)
+
@sandbox_demobank.command("info", help="Return basic information of a bank
account")
@click.option(
"--bank-account",
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 2bce4079..10d4b042 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -226,7 +226,7 @@ fun wireTransfer(
return wireTransfer(
debitAccount = args.first,
creditAccount = args.second,
- Demobank = args.third,
+ demobank = args.third,
subject = subject,
amount = amountObj.amount.toPlainString()
)
@@ -244,7 +244,7 @@ fun wireTransfer(
fun wireTransfer(
debitAccount: BankAccountEntity,
creditAccount: BankAccountEntity,
- Demobank: DemobankConfigEntity,
+ demobank: DemobankConfigEntity,
subject: String,
amount: String,
): String {
@@ -262,12 +262,12 @@ fun wireTransfer(
debtorName = getPersonNameFromCustomer(debitAccount.owner)
this.subject = subject
this.amount = amount
- this.currency = Demobank.currency
+ this.currency = demobank.currency
date = timeStamp
accountServicerReference = transactionRef
account = creditAccount
direction = "CRDT"
- this.demobank = Demobank
+ this.demobank = demobank
}
BankAccountTransactionEntity.new {
creditorIban = creditAccount.iban
@@ -278,12 +278,12 @@ fun wireTransfer(
debtorName = getPersonNameFromCustomer(debitAccount.owner)
this.subject = subject
this.amount = amount
- this.currency = Demobank.currency
+ this.currency = demobank.currency
date = timeStamp
accountServicerReference = transactionRef
account = debitAccount
direction = "DBIT"
- demobank = Demobank
+ this.demobank = demobank
}
}
return transactionRef
@@ -306,10 +306,10 @@ fun getBankAccountFromPayto(paytoUri: String):
BankAccountEntity {
fun getBankAccountFromIban(iban: String): BankAccountEntity {
return transaction {
- BankAccountEntity.find(BankAccountsTable.iban eq iban)
- }.firstOrNull() ?: throw SandboxError(
+ BankAccountEntity.find(BankAccountsTable.iban eq iban).firstOrNull()
+ } ?: throw SandboxError(
HttpStatusCode.NotFound,
- "Did not find a bank account for ${iban}"
+ "Did not find a bank account for $iban"
)
}
@@ -385,4 +385,32 @@ fun getEbicsSubscriberFromDetails(userID: String,
partnerID: String, hostID: Str
"Ebics subscriber not found"
)
}
+}
+
+/**
+ * This helper tries to:
+ * 1. Authenticate the client.
+ * 2. Extract the bank account's label from the request's path
+ * 3. Return the bank account DB object if the client has access to it.
+ */
+fun getBankAccountWithAuth(call: ApplicationCall): BankAccountEntity {
+ val username = call.request.basicAuth()
+ val accountAccessed = call.getUriComponent("account_name")
+ val demobank = ensureDemobank(call)
+ val bankAccount = transaction {
+ val res = BankAccountEntity.find {
+ (BankAccountsTable.label eq accountAccessed).and(
+ BankAccountsTable.demoBank eq demobank.id
+ )
+ }.firstOrNull()
+ res
+ } ?: throw notFound("Account '$accountAccessed' not found")
+ // Check rights.
+ if (
+ WITH_AUTH
+ && (bankAccount.owner != username && username != "admin")
+ ) throw forbidden(
+ "Customer '$username' cannot access bank account '$accountAccessed'"
+ )
+ return bankAccount
}
\ No newline at end of file
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
index a25503b8..7f19d2e3 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
@@ -122,3 +122,13 @@ data class TalerWithdrawalSelection(
val reserve_pub: String,
val selected_exchange: String?
)
+
+data class NewTransactionReq(
+ /**
+ * This Payto address must contain the wire transfer
+ * subject among its query parameters -- 'message' parameter.
+ */
+ val paytoUri: String,
+ // $currency:X.Y format
+ val amount: String
+)
\ No newline at end of file
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 5cdd8cd5..08945b33 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -84,7 +84,7 @@ val logger: Logger =
LoggerFactory.getLogger("tech.libeufin.sandbox")
private val currencyEnv: String? = System.getenv("LIBEUFIN_SANDBOX_CURRENCY")
const val SANDBOX_DB_ENV_VAR_NAME = "LIBEUFIN_SANDBOX_DB_CONNECTION"
private val adminPassword: String? =
System.getenv("LIBEUFIN_SANDBOX_ADMIN_PASSWORD")
-private var WITH_AUTH = true
+var WITH_AUTH = true // Needed by helpers too, hence not making it private.
data class SandboxError(
val statusCode: HttpStatusCode,
@@ -1070,6 +1070,33 @@ val sandboxApp: Application.() -> Unit = {
}
// Talk to Web UI.
route("/access-api") {
+ post("/accounts/{account_name}/transactions") {
+ val bankAccount = getBankAccountWithAuth(call)
+ val req = call.receive<NewTransactionReq>()
+ val payto = parsePayto(req.paytoUri)
+ val amount = parseAmount(req.amount)
+ /**
+ * Need a transaction block only to let the
+ * 'demoBank' field of 'bankAccount' accessed.
+ *
+ * This could be fixed by making 'getBankAccountWithAuth()'
+ * return a pair, consisting of the bank account and the
demobank
+ * hosting it.
+ */
+ transaction {
+ wireTransfer(
+ debitAccount = bankAccount,
+ creditAccount = getBankAccountFromIban(payto.iban),
+ demobank = bankAccount.demoBank,
+ subject = payto.message ?: throw badRequest(
+ "'message' query parameter missing in Payto
address"
+ ),
+ amount = amount.amount.toPlainString()
+ )
+ }
+ call.respond(object {})
+ return@post
+ }
// Information about one withdrawal.
get("/accounts/{account_name}/withdrawals/{withdrawal_id}") {
val op =
getWithdrawalOperation(call.getUriComponent("withdrawal_id"))
@@ -1178,7 +1205,7 @@ val sandboxApp: Application.() -> Unit = {
"Cannot transfer funds without reserve
public key."
),
// provide the currency.
- Demobank = ensureDemobank(call)
+ demobank = ensureDemobank(call)
)
wo.confirmationDone = true
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: Access API: implement create transactions.,
gnunet <=