diff options
author | Antoine A <> | 2024-03-06 10:42:20 +0100 |
---|---|---|
committer | Antoine A <> | 2024-03-06 10:42:20 +0100 |
commit | 807eb3fa7eb4a0d555646865a370f5f66cbaa4fc (patch) | |
tree | 5d9116a7dc3a69da777bc6c7b1e091ea5c565e02 | |
parent | 9af4fd9bcb338f20e75254f1aaad9ee7b1c0df47 (diff) | |
download | libeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.tar.gz libeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.tar.bz2 libeufin-807eb3fa7eb4a0d555646865a370f5f66cbaa4fc.zip |
Clean and refactor code
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") |