summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-03-06 10:42:20 +0100
committerAntoine A <>2024-03-06 10:42:20 +0100
commit807eb3fa7eb4a0d555646865a370f5f66cbaa4fc (patch)
tree5d9116a7dc3a69da777bc6c7b1e091ea5c565e02
parent9af4fd9bcb338f20e75254f1aaad9ee7b1c0df47 (diff)
downloadlibeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.tar.gz
libeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.tar.bz2
libeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.zip
Clean and refactor code
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/Main.kt1
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/api/BankIntegrationApi.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt)9
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/api/ConversionApi.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt)5
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt)17
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/api/RevenueApi.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt)5
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt)5
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt2
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/helpers.kt38
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/params.kt (renamed from bank/src/main/kotlin/tech/libeufin/bank/Params.kt)17
-rw-r--r--bank/src/test/kotlin/BankIntegrationApiTest.kt7
-rw-r--r--bank/src/test/kotlin/CoreBankApiTest.kt7
11 files changed, 65 insertions, 48 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
index 4b2c63fc..0baa78be 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -62,6 +62,7 @@ import java.util.zip.Inflater
import kotlin.io.path.Path
import kotlin.io.path.exists
import kotlin.io.path.readText
+import tech.libeufin.bank.api.*
private val logger: Logger = LoggerFactory.getLogger("libeufin-bank")
// Dirty local variable to stop the server in test TODO remove this ugly hack
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/BankIntegrationApi.kt
index 17d2a917..05505214 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/api/BankIntegrationApi.kt
@@ -19,13 +19,14 @@
/* This file contains the Taler Integration API endpoints,
* that are typically requested by wallets. */
-package tech.libeufin.bank
+package tech.libeufin.bank.api
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
+import tech.libeufin.bank.*
import tech.libeufin.bank.db.AbortResult
import tech.libeufin.bank.db.Database
import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalSelectionResult
@@ -41,7 +42,7 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) {
// Note: wopid acts as an authentication token.
get("/taler-integration/withdrawal-operation/{wopid}") {
- val uuid = call.uuidParameter("wopid")
+ val uuid = call.uuidPath("wopid")
val params = StatusParams.extract(call.request.queryParameters)
val op = db.withdrawal.pollStatus(uuid, params, ctx.wireMethod) ?: throw notFound(
"Withdrawal operation '$uuid' not found",
@@ -53,7 +54,7 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) {
))
}
post("/taler-integration/withdrawal-operation/{wopid}") {
- val uuid = call.uuidParameter("wopid")
+ val uuid = call.uuidPath("wopid")
val req = call.receive<BankWithdrawalOperationPostRequest>()
val res = db.withdrawal.setDetails(
@@ -90,7 +91,7 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) {
}
}
post("/taler-integration/withdrawal-operation/{wopid}/abort") {
- val uuid = call.uuidParameter("wopid")
+ val uuid = call.uuidPath("wopid")
when (db.withdrawal.abort(uuid)) {
AbortResult.UnknownOperation -> throw notFound(
"Withdrawal operation '$uuid' not found",
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/ConversionApi.kt
index 168b2034..8dcc1f60 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/api/ConversionApi.kt
@@ -1,6 +1,6 @@
/*
* This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
+ * Copyright (C) 2023-2024 Taler Systems S.A.
* LibEuFin is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -16,13 +16,14 @@
* License along with LibEuFin; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.bank
+package tech.libeufin.bank.api
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
+import tech.libeufin.bank.*
import tech.libeufin.bank.auth.authAdmin
import tech.libeufin.bank.db.ConversionDAO
import tech.libeufin.bank.db.ConversionDAO.ConversionResult
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt
index 4b6a6e53..feaa84df 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt
@@ -16,7 +16,7 @@
* License along with LibEuFin; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.bank
+package tech.libeufin.bank.api
import io.ktor.http.*
import io.ktor.server.application.*
@@ -39,6 +39,7 @@ import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult
import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalConfirmationResult
import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult
import tech.libeufin.common.*
+import tech.libeufin.bank.*
import java.time.Duration
import java.time.Instant
import java.time.temporal.ChronoUnit
@@ -434,7 +435,7 @@ private fun Routing.coreBankTransactionsApi(db: Database, ctx: BankConfig) {
}
}
get("/accounts/{USERNAME}/transactions/{T_ID}") {
- val tId = call.longParameter("T_ID")
+ val tId = call.longPath("T_ID")
val tx = db.transaction.get(tId, username, ctx.payto) ?: throw notFound(
"Bank transaction '$tId' not found",
TalerErrorCode.BANK_TRANSACTION_NOT_FOUND
@@ -510,7 +511,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) {
}
}
post("/accounts/{USERNAME}/withdrawals/{withdrawal_id}/confirm") {
- val id = call.uuidParameter("withdrawal_id")
+ val id = call.uuidPath("withdrawal_id")
val challenge = call.checkChallenge(db, Operation.withdrawal)
when (db.withdrawal.confirm(username, id, Instant.now(), challenge != null)) {
WithdrawalConfirmationResult.UnknownOperation -> throw notFound(
@@ -540,7 +541,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) {
}
}
post("/accounts/{USERNAME}/withdrawals/{withdrawal_id}/abort") {
- val opId = call.uuidParameter("withdrawal_id")
+ val opId = call.uuidPath("withdrawal_id")
when (db.withdrawal.abort(opId)) {
AbortResult.UnknownOperation -> throw notFound(
"Withdrawal operation $opId not found",
@@ -555,7 +556,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) {
}
}
get("/withdrawals/{withdrawal_id}") {
- val uuid = call.uuidParameter("withdrawal_id")
+ val uuid = call.uuidPath("withdrawal_id")
val params = StatusParams.extract(call.request.queryParameters)
val op = db.withdrawal.pollInfo(uuid, params) ?: throw notFound(
"Withdrawal operation '$uuid' not found",
@@ -613,7 +614,7 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) = conditio
}
auth(db, TokenScope.readonly) {
get("/accounts/{USERNAME}/cashouts/{CASHOUT_ID}") {
- val id = call.longParameter("CASHOUT_ID")
+ val id = call.longPath("CASHOUT_ID")
val cashout = db.cashout.get(id, username) ?: throw notFound(
"Cashout operation $id not found",
TalerErrorCode.BANK_TRANSACTION_NOT_FOUND
@@ -646,7 +647,7 @@ private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) = conditio
private fun Routing.coreBankTanApi(db: Database, ctx: BankConfig) {
auth(db, TokenScope.readwrite) {
post("/accounts/{USERNAME}/challenge/{CHALLENGE_ID}") {
- val id = call.longParameter("CHALLENGE_ID")
+ val id = call.longPath("CHALLENGE_ID")
val res = db.tan.send(
id = id,
login = username,
@@ -708,7 +709,7 @@ private fun Routing.coreBankTanApi(db: Database, ctx: BankConfig) {
}
}
post("/accounts/{USERNAME}/challenge/{CHALLENGE_ID}/confirm") {
- val id = call.longParameter("CHALLENGE_ID")
+ val id = call.longPath("CHALLENGE_ID")
val req = call.receive<ChallengeSolve>()
val code = req.tan.removePrefix("T-")
val res = db.tan.solve(
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/RevenueApi.kt
index fe16a23c..f91054ce 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/api/RevenueApi.kt
@@ -1,6 +1,6 @@
/*
* This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
+ * Copyright (C) 2023-2024 Taler Systems S.A.
* LibEuFin is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -16,12 +16,13 @@
* License along with LibEuFin; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.bank
+package tech.libeufin.bank.api
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
+import tech.libeufin.bank.*
import tech.libeufin.bank.auth.auth
import tech.libeufin.bank.db.Database
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt
index f1a6a880..5b10f7d1 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt
@@ -1,6 +1,6 @@
/*
* This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
+ * Copyright (C) 2023-2024 Taler Systems S.A.
* LibEuFin is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -19,7 +19,7 @@
// This file contains the Taler Wire Gateway API handlers.
-package tech.libeufin.bank
+package tech.libeufin.bank.api
import io.ktor.http.*
import io.ktor.server.application.*
@@ -27,6 +27,7 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.util.pipeline.*
+import tech.libeufin.bank.*
import tech.libeufin.bank.auth.auth
import tech.libeufin.bank.auth.authAdmin
import tech.libeufin.bank.auth.username
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
index 7e8f4aac..577da51d 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt
@@ -38,7 +38,7 @@ private val AUTH_IS_ADMIN = AttributeKey<Boolean>("is_admin")
private val AUTH_TOKEN = AttributeKey<ByteArray>("auth_token")
/** Get username of the request account */
-val ApplicationCall.username: String get() = expectParameter("USERNAME")
+val ApplicationCall.username: String get() = parameters.expect("USERNAME")
/** Get username of the request account */
val PipelineContext<Unit, ApplicationCall>.username: String get() = call.username
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
index dd827f2b..f8c5f25b 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -39,11 +39,23 @@ import tech.libeufin.bank.db.Database
import tech.libeufin.common.*
import java.util.*
-fun ApplicationCall.expectParameter(name: String) =
- parameters[name] ?: throw badRequest(
- "Missing '$name' param",
- TalerErrorCode.GENERIC_PARAMETER_MISSING
- )
+fun ApplicationCall.uuidPath(name: String): UUID {
+ val value = parameters[name]!!
+ try {
+ return UUID.fromString(value)
+ } catch (e: Exception) {
+ throw badRequest("UUID uri component malformed: ${e.message}", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // TODO better error ?
+ }
+}
+
+fun ApplicationCall.longPath(name: String): Long {
+ val value = parameters[name]!!
+ try {
+ return value.toLong()
+ } catch (e: Exception) {
+ throw badRequest("Long uri component malformed: ${e.message}", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // TODO better error ?
+ }
+}
/** Retrieve the bank account info for the selected username*/
suspend fun ApplicationCall.bankInfo(db: Database, ctx: BankPaytoCtx): BankInfo
@@ -82,22 +94,6 @@ fun ApplicationRequest.withdrawConfirmUrl(id: UUID) = url {
appendEncodedPathSegments("webui", "#", "operation", id.toString())
}
-fun ApplicationCall.uuidParameter(name: String): UUID {
- try {
- return UUID.fromString(expectParameter(name))
- } catch (e: Exception) {
- throw badRequest("UUID uri component malformed: ${e.message}")
- }
-}
-
-fun ApplicationCall.longParameter(name: String): Long {
- try {
- return expectParameter(name).toLong()
- } catch (e: Exception) {
- throw badRequest("Long uri component malformed: ${e.message}")
- }
-}
-
/**
* This function creates the admin account ONLY IF it was
* NOT found in the database. It sets it to a random password that
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt b/bank/src/main/kotlin/tech/libeufin/bank/params.kt
index 59210164..f0c6e474 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/params.kt
@@ -25,17 +25,30 @@ import tech.libeufin.common.TalerErrorCode
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.temporal.TemporalAdjusters
+import java.util.UUID
fun Parameters.expect(name: String): String
= get(name) ?: throw badRequest("Missing '$name' parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING)
fun Parameters.int(name: String): Int?
- = get(name)?.run { toIntOrNull() ?: throw badRequest("Param 'which' not a number", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) }
+ = get(name)?.run { toIntOrNull() ?: throw badRequest("Param '$name' not a number", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) }
fun Parameters.expectInt(name: String): Int
= int(name) ?: throw badRequest("Missing '$name' number parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING)
fun Parameters.long(name: String): Long?
- = get(name)?.run { toLongOrNull() ?: throw badRequest("Param 'which' not a number", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) }
+ = get(name)?.run { toLongOrNull() ?: throw badRequest("Param '$name' not a number", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) }
fun Parameters.expectLong(name: String): Long
= long(name) ?: throw badRequest("Missing '$name' number parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING)
+fun Parameters.uuid(name: String): UUID? {
+ return get(name)?.run {
+ try {
+ UUID.fromString(this)
+ } catch (e: Exception) {
+ println("$this $e")
+ throw badRequest("Param '$name' not an UUID", TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
+ }
+ }
+}
+fun Parameters.expectUuid(name: String): UUID
+ = uuid(name) ?: throw badRequest("Missing '$name' UUID parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING)
fun Parameters.amount(name: String): TalerAmount?
= get(name)?.run {
try {
diff --git a/bank/src/test/kotlin/BankIntegrationApiTest.kt b/bank/src/test/kotlin/BankIntegrationApiTest.kt
index ba5ff624..2fe33d63 100644
--- a/bank/src/test/kotlin/BankIntegrationApiTest.kt
+++ b/bank/src/test/kotlin/BankIntegrationApiTest.kt
@@ -63,7 +63,7 @@ class BankIntegrationApiTest {
// Check bad UUID
client.get("/taler-integration/withdrawal-operation/chocolate")
- .assertBadRequest()
+ .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
}
// POST /taler-integration/withdrawal-operation/UUID
@@ -78,7 +78,7 @@ class BankIntegrationApiTest {
// Check bad UUID
client.post("/taler-integration/withdrawal-operation/chocolate") {
json(req)
- }.assertBadRequest()
+ }.assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
// Check unknown
client.post("/taler-integration/withdrawal-operation/${UUID.randomUUID()}") {
@@ -180,7 +180,8 @@ class BankIntegrationApiTest {
}
// Check bad UUID
- client.postA("/taler-integration/withdrawal-operation/chocolate/abort").assertBadRequest()
+ client.postA("/taler-integration/withdrawal-operation/chocolate/abort")
+ .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
// Check unknown
client.postA("/taler-integration/withdrawal-operation/${UUID.randomUUID()}/abort")
diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt
index 9c561391..f5f668f5 100644
--- a/bank/src/test/kotlin/CoreBankApiTest.kt
+++ b/bank/src/test/kotlin/CoreBankApiTest.kt
@@ -1021,7 +1021,7 @@ class CoreBankWithdrawalApiTest {
statusRoutine<WithdrawalPublicInfo>("/withdrawals") { it.status }
// Check bad UUID
- client.get("/withdrawals/chocolate").assertBadRequest()
+ client.get("/withdrawals/chocolate").assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
// Check unknown
client.get("/withdrawals/${UUID.randomUUID()}")
@@ -1098,7 +1098,8 @@ class CoreBankWithdrawalApiTest {
}
// Check bad UUID
- client.postA("/accounts/merchant/withdrawals/chocolate/confirm").assertBadRequest()
+ client.postA("/accounts/merchant/withdrawals/chocolate/confirm")
+ .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
// Check unknown
client.postA("/accounts/merchant/withdrawals/${UUID.randomUUID()}/confirm")
@@ -1231,7 +1232,7 @@ class CoreBankCashoutApiTest {
// Check bad UUID
client.getA("/accounts/customer/cashouts/chocolate")
- .assertBadRequest()
+ .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED)
// Check unknown
client.getA("/accounts/customer/cashouts/42")