[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: Snack-machine demo changes.
From: |
gnunet |
Subject: |
[libeufin] branch master updated: Snack-machine demo changes. |
Date: |
Wed, 04 May 2022 10:49:15 +0200 |
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 e9cc8a8e Snack-machine demo changes.
e9cc8a8e is described below
commit e9cc8a8e44b6ad1269a53056500b45d564dc091b
Author: ms <ms@taler.net>
AuthorDate: Wed May 4 10:46:47 2022 +0200
Snack-machine demo changes.
- set creditor name
- make signup bonus optional
- make currency mandatory on the CLI (simulate-incoming-transaction
subcommand)
---
cli/bin/libeufin-cli | 14 ++++++++--
.../src/main/kotlin/tech/libeufin/sandbox/DB.kt | 2 ++
.../main/kotlin/tech/libeufin/sandbox/Helpers.kt | 10 +++++--
.../src/main/kotlin/tech/libeufin/sandbox/JSON.kt | 4 ++-
.../src/main/kotlin/tech/libeufin/sandbox/Main.kt | 32 ++++++++++++++--------
util/src/main/kotlin/amounts.kt | 15 ++++++++++
6 files changed, 58 insertions(+), 19 deletions(-)
diff --git a/cli/bin/libeufin-cli b/cli/bin/libeufin-cli
index 956859ff..e40c8f1a 100755
--- a/cli/bin/libeufin-cli
+++ b/cli/bin/libeufin-cli
@@ -1273,13 +1273,21 @@ def sandbox_demobank_info(obj, bank_account):
default=False,
help="Decides whether a bank account is public.",
)
+@click.option(
+ "--name",
+ default=False,
+ help="Person name",
+)
@click.pass_obj
-def sandbox_demobank_register(obj, public):
+def sandbox_demobank_register(obj, public, name):
url = obj.access_api_url ("/testing/register")
+ req = dict(username=obj.username, password=obj.password, isPublic=public)
+ if name:
+ req.update(name=name)
try:
resp = post(
url,
- json=dict(username=obj.username, password=obj.password,
isPublic=public),
+ json=req,
)
except Exception as e:
print(e)
@@ -1386,7 +1394,7 @@ def bankaccount_generate_transactions(obj, account_label):
@click.option(
"--debtor-name", help="name of the person who is sending the payment",
prompt=True
)
-@click.option("--amount", help="amount, no currency", prompt=True)
+@click.option("--amount", help="amount with currency (currency:x.y)",
prompt=True)
@click.option("--subject", help="payment subject", prompt=True)
@click.pass_obj
def simulate_incoming_transaction(
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
index caf82ad5..c2dd5662 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -92,6 +92,7 @@ enum class KeyState {
object DemobankConfigsTable : LongIdTable() {
val currency = text("currency")
val allowRegistrations = bool("allowRegistrations")
+ val withSignupBonus = bool("withSignupBonus")
val bankDebtLimit = integer("bankDebtLimit")
val usersDebtLimit = integer("usersDebtLimit")
val name = text("hostname")
@@ -103,6 +104,7 @@ class DemobankConfigEntity(id: EntityID<Long>) :
LongEntity(id) {
companion object :
LongEntityClass<DemobankConfigEntity>(DemobankConfigsTable)
var currency by DemobankConfigsTable.currency
var allowRegistrations by DemobankConfigsTable.allowRegistrations
+ var withSignupBonus by DemobankConfigsTable.withSignupBonus
var bankDebtLimit by DemobankConfigsTable.bankDebtLimit
var usersDebtLimit by DemobankConfigsTable.usersDebtLimit
var name by DemobankConfigsTable.name
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
index 372fc9cc..b02307f9 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Helpers.kt
@@ -136,7 +136,10 @@ fun getCustomer(username: String): DemobankCustomerEntity {
/**
* Get person name from a customer's username.
*/
-fun getPersonNameFromCustomer(ownerUsername: String): String {
+fun getPersonNameFromCustomer(ownerUsername: String?): String {
+ if (ownerUsername == null) {
+ return "Name unknown"
+ }
return when (ownerUsername) {
"admin" -> "admin" // Could be changed to Admin, or some different
value.
"bank" -> "The Bank"
@@ -146,7 +149,7 @@ fun getPersonNameFromCustomer(ownerUsername: String):
String {
).firstOrNull() ?: throw internalServerError(
"Person name of '$ownerUsername' not found"
)
- ownerCustomer.name ?: "Unknown"
+ ownerCustomer.name ?: "Name unknown"
}
}
}
@@ -170,7 +173,7 @@ fun getDefaultDemobank(): DemobankConfigEntity {
)
}
-fun maybeCreateDefaultDemobank() {
+fun maybeCreateDefaultDemobank(withSignupBonus: Boolean = false) {
transaction {
if (DemobankConfigEntity.all().empty()) {
DemobankConfigEntity.new {
@@ -179,6 +182,7 @@ fun maybeCreateDefaultDemobank() {
usersDebtLimit = 10000
allowRegistrations = true
name = "default"
+ this.withSignupBonus = withSignupBonus
}
// Give one demobank a own bank account, mainly to award
// customer upon registration.
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
index 33cc8531..4636850f 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/JSON.kt
@@ -95,7 +95,9 @@ data class CustomerRegistration(
val password: String,
val isPublic: Boolean = false,
// When missing, it's autogenerated.
- val iban: String?
+ val iban: String?,
+ // When missing, stays null in the DB.
+ val name: String?
)
// Could be used as a general bank account info container.
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
index 142b6ed2..2cae0f34 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt
@@ -295,6 +295,10 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
help = "Bind the Sandbox to the Unix domain socket at PATH.
Overrides" +
" --port, when both are given", metavar = "PATH"
)
+ private val withSignupBonus by option(
+ "--with-signup-bonus",
+ help = "Award new customers with 100 units of currency!"
+ ).flag("--without-signup-bonus", default = false)
override fun run() {
WITH_AUTH = auth
@@ -305,7 +309,7 @@ class Serve : CliktCommand("Run sandbox HTTP server") {
exitProcess(1)
}
execThrowableOrTerminate {
dbCreateTables(getDbConnFromEnv(SANDBOX_DB_ENV_VAR_NAME)) }
- maybeCreateDefaultDemobank()
+ maybeCreateDefaultDemobank(withSignupBonus)
if (withUnixSocket != null) {
startServer(
withUnixSocket ?: throw Exception("Could not use the Unix
domain socket path value!"),
@@ -590,16 +594,10 @@ val sandboxApp: Application.() -> Unit = {
// Book one incoming payment for the requesting account.
// The debtor is not required to have an account at this Sandbox.
post("/admin/bank-accounts/{label}/simulate-incoming-transaction") {
- call.request.basicAuth()
+ val username = call.request.basicAuth()
val body = call.receiveJson<IncomingPaymentInfo>()
// FIXME: generate nicer UUID!
val accountLabel = ensureNonNull(call.parameters["label"])
- if (!validatePlainAmount(body.amount)) {
- throw SandboxError(
- HttpStatusCode.BadRequest,
- "invalid amount (should be plain amount without currency)"
- )
- }
val reqDebtorBic = body.debtorBic
if (reqDebtorBic != null && !validateBic(reqDebtorBic)) {
throw SandboxError(
@@ -607,8 +605,16 @@ val sandboxApp: Application.() -> Unit = {
"invalid BIC"
)
}
+ val (amount, currency) = parseAmountAsString(body.amount)
transaction {
val demobank = getDefaultDemobank()
+ /**
+ * This API needs compatibility with the currency-less format.
+ */
+ if (currency != null) {
+ if (currency != demobank.currency)
+ throw SandboxError(HttpStatusCode.BadRequest,
"Currency ${currency} not supported.")
+ }
val account = getBankAccountFromLabel(
accountLabel, demobank
)
@@ -616,18 +622,18 @@ val sandboxApp: Application.() -> Unit = {
BankAccountTransactionEntity.new {
creditorIban = account.iban
creditorBic = account.bic
- creditorName = "Creditor Name" // FIXME: Waits to get this
value from the DemobankCustomer type.
+ creditorName = getPersonNameFromCustomer(username)
debtorIban = body.debtorIban
debtorBic = reqDebtorBic
debtorName = body.debtorName
subject = body.subject
- amount = body.amount
+ this.amount = amount
date = getUTCnow().toInstant().toEpochMilli()
accountServicerReference = "sandbox-$randId"
this.account = account
direction = "CRDT"
this.demobank = demobank
- currency = demobank.currency
+ this.currency = demobank.currency
}
}
call.respond(object {})
@@ -1436,8 +1442,10 @@ val sandboxApp: Application.() -> Unit = {
DemobankCustomerEntity.new {
username = req.username
passwordHash = CryptoUtil.hashpw(req.password)
+ name = req.name // nullable
}
- bankAccount.bonus("${demobank.currency}:100")
+ if (demobank.withSignupBonus)
+ bankAccount.bonus("${demobank.currency}:100")
bankAccount
}
val balance = balanceForAccount(bankAccount)
diff --git a/util/src/main/kotlin/amounts.kt b/util/src/main/kotlin/amounts.kt
index 327bcbd4..5528a35b 100644
--- a/util/src/main/kotlin/amounts.kt
+++ b/util/src/main/kotlin/amounts.kt
@@ -28,6 +28,21 @@ fun validatePlainAmount(plainAmount: String): Boolean {
return re.matches(plainAmount)
}
+/**
+ * Parse an "amount" where the currency is optional. It returns
+ * a pair where the first item is always the amount, and the second
+ * is the currency or null (when this one wasn't given in the input)
+ */
+fun parseAmountAsString(amount: String): Pair<String, String?> {
+ val match = Regex("^([A-Z]+:)?([0-9]+(\\.[0-9]+)?)$").find(amount) ?: throw
+ UtilError(HttpStatusCode.BadRequest, "invalid amount: $amount")
+ var (currency, number) = match.destructured
+ // Currency given, need to strip the ":".
+ if (currency.isNotEmpty())
+ currency = currency.dropLast(1)
+ return Pair(number, if (currency.isEmpty()) null else currency)
+}
+
fun parseAmount(amount: String): AmountWithCurrency {
val match = Regex("([A-Z]+):([0-9]+(\\.[0-9]+)?)").find(amount) ?: throw
UtilError(HttpStatusCode.BadRequest, "invalid amount: $amount")
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.