[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: Taler URI generator.
From: |
gnunet |
Subject: |
[libeufin] branch master updated: Taler URI generator. |
Date: |
Tue, 19 Sep 2023 14:55:45 +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 b0e1a2b3 Taler URI generator.
b0e1a2b3 is described below
commit b0e1a2b3cd3eb0ce3c6f6567570f019fe9a36900
Author: MS <ms@taler.net>
AuthorDate: Tue Sep 19 14:55:30 2023 +0200
Taler URI generator.
---
.../src/main/kotlin/tech/libeufin/bank/Database.kt | 1 +
bank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 36 +++++++++++++++++++++-
.../kotlin/tech/libeufin/bank/talerWebHandlers.kt | 31 ++++++++++++++++++-
bank/src/main/kotlin/tech/libeufin/bank/types.kt | 7 +++++
bank/src/test/kotlin/TalerTest.kt | 34 ++++++++++++++++++++
5 files changed, 107 insertions(+), 2 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt
b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt
index 8b45e146..64fe9afa 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt
@@ -32,6 +32,7 @@ private const val DB_CTR_LIMIT = 1000000
fun Customer.expectRowId(): Long = this.dbRowId ?: throw
internalServerError("Cutsomer '$login' had no DB row ID.")
fun BankAccount.expectBalance(): TalerAmount = this.balance ?: throw
internalServerError("Bank account '${this.internalPaytoUri}' lacks balance.")
+fun BankAccount.expectRowId(): Long = this.bankAccountId ?: throw
internalServerError("Bank account '${this.internalPaytoUri}' lacks database row
ID.")
class Database(private val dbConfig: String) {
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
index 1431ff4f..59ddb318 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -21,10 +21,12 @@ package tech.libeufin.bank
import io.ktor.http.*
import io.ktor.server.application.*
+import io.ktor.server.util.*
import net.taler.common.errorcodes.TalerErrorCode
import net.taler.wallet.crypto.Base32Crockford
import tech.libeufin.util.*
import java.lang.NumberFormatException
+import java.net.URL
fun ApplicationCall.expectUriComponent(componentName: String) =
this.maybeUriComponent(componentName) ?: throw badRequest(
@@ -335,4 +337,36 @@ fun isBalanceEnough(
(normalDiff.frac > normalMaxDebt.frac)) return false
return true
}
-fun getBankCurrency(): String = db.configGet("internal_currency") ?: throw
internalServerError("Bank lacks currency")
\ No newline at end of file
+fun getBankCurrency(): String = db.configGet("internal_currency") ?: throw
internalServerError("Bank lacks currency")
+
+/**
+ * Builds the taler://withdraw-URI. Such URI will serve the requests
+ * from wallets, when they need to manage the operation. For example,
+ * a URI like taler://withdraw/$BANK_URL/taler-integration/$WO_ID needs
+ * the bank to implement the Taler integratino API at the following base URL:
+ *
+ * https://$BANK_URL/taler-integration
+ */
+fun getTalerWithdrawUri(baseUrl: String, woId: String) =
+ url {
+ val baseUrlObj = URL(baseUrl)
+ protocol = URLProtocol(
+ name = "taler".plus(if (baseUrlObj.protocol.lowercase() == "http")
"+http" else ""),
+ defaultPort = -1
+ )
+ host = "withdraw"
+ val pathSegments = mutableListOf(
+ // adds the hostname(+port) of the actual bank that will serve the
withdrawal request.
+ baseUrlObj.host.plus(
+ if (baseUrlObj.port != -1)
+ ":${baseUrlObj.port}"
+ else ""
+ )
+ )
+ // Removing potential double slashes.
+ baseUrlObj.path.split("/").forEach {
+ if (it.isNotEmpty()) pathSegments.add(it)
+ }
+ pathSegments.add("taler-integration/${woId}")
+ this.appendPathSegments(pathSegments)
+ }
\ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt
b/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt
index 6bb27374..8d6fd3d6 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/talerWebHandlers.kt
@@ -26,7 +26,10 @@ package tech.libeufin.bank
import io.ktor.server.application.*
import io.ktor.server.request.*
+import io.ktor.server.response.*
import io.ktor.server.routing.*
+import net.taler.common.errorcodes.TalerErrorCode
+import java.util.*
fun Routing.talerWebHandlers() {
post("/accounts/{USERNAME}/withdrawals") {
@@ -39,8 +42,34 @@ fun Routing.talerWebHandlers() {
// Checking that the user has enough funds.
val b = db.bankAccountGetFromOwnerId(c.expectRowId())
?: throw internalServerError("Customer '${c.login}' lacks bank
account.")
+ val withdrawalAmount = parseTalerAmount(req.amount)
+ if (
+ !isBalanceEnough(
+ balance = b.expectBalance(),
+ due = withdrawalAmount,
+ maxDebt = b.maxDebt,
+ hasBalanceDebt = b.hasDebt
+ ))
+ throw forbidden(
+ hint = "Insufficient funds to withdraw with Taler",
+ talerErrorCode = TalerErrorCode.TALER_EC_NONE // FIXME: need
EC.
+ )
+ // Auth and funds passed, create the operation now!
+ val opId = UUID.randomUUID()
+ if(
+ !db.talerWithdrawalCreate(
+ opId,
+ b.expectRowId(),
+ withdrawalAmount
+ )
+ )
+ throw internalServerError("Bank failed at creating the withdraw
operation.")
- throw NotImplementedError()
+ call.respond(BankAccountCreateWithdrawalResponse(
+ withdrawal_id = opId.toString(),
+ taler_withdraw_uri = "FIXME"
+ ))
+ return@post
}
get("/accounts/{USERNAME}/withdrawals/{W_ID}") {
throw NotImplementedError()
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/types.kt
b/bank/src/main/kotlin/tech/libeufin/bank/types.kt
index 92567634..ebbb0f1e 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/types.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/types.kt
@@ -388,3 +388,10 @@ data class BankAccountTransactionsResponse(
data class BankAccountCreateWithdrawalRequest(
val amount: String
)
+
+// Taler withdrawal response.
+@Serializable
+data class BankAccountCreateWithdrawalResponse(
+ val withdrawal_id: String,
+ val taler_withdraw_uri: String
+)
diff --git a/bank/src/test/kotlin/TalerTest.kt
b/bank/src/test/kotlin/TalerTest.kt
new file mode 100644
index 00000000..2aa90e2d
--- /dev/null
+++ b/bank/src/test/kotlin/TalerTest.kt
@@ -0,0 +1,34 @@
+import org.junit.Test
+import tech.libeufin.bank.getTalerWithdrawUri
+
+class TalerTest {
+ // Testing the generation of taler://withdraw-URIs.
+ @Test
+ fun testWithdrawUri() {
+ // Checking the taler+http://-style.
+ val withHttp = getTalerWithdrawUri(
+ "http://example.com",
+ "my-id"
+ )
+ assert(withHttp ==
"taler+http://withdraw/example.com/taler-integration/my-id")
+ // Checking the taler://-style
+ val onlyTaler = getTalerWithdrawUri(
+ "https://example.com/",
+ "my-id"
+ )
+ // Note: this tests as well that no double slashes belong to the result
+ assert(onlyTaler ==
"taler://withdraw/example.com/taler-integration/my-id")
+ // Checking the removal of subsequent slashes
+ val manySlashes = getTalerWithdrawUri(
+ "https://www.example.com//////",
+ "my-id"
+ )
+ assert(manySlashes ==
"taler://withdraw/www.example.com/taler-integration/my-id")
+ // Checking with specified port number
+ val withPort = getTalerWithdrawUri(
+ "https://www.example.com:9876",
+ "my-id"
+ )
+ assert(withPort ==
"taler://withdraw/www.example.com:9876/taler-integration/my-id")
+ }
+}
\ No newline at end of file
--
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: Taler URI generator.,
gnunet <=