commit 6ec304b214ef21445175fac36f861237de4d0aaa
parent 554a31357786dc80cd5db5310b184ca532747566
Author: Antoine A <>
Date: Fri, 10 Nov 2023 13:52:10 +0000
Improve cashout API
Diffstat:
5 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt b/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt
@@ -75,19 +75,6 @@ val PipelineContext<Unit, ApplicationCall>.isAdmin: Boolean get() = call.isAdmin
val ApplicationCall.username: String get() = expectUriComponent("USERNAME")
val ApplicationCall.isAdmin: Boolean get() = attributes.getOrNull(AUTH_IS_ADMIN) ?: false
-private fun Route.intercept(callback: Route.() -> Unit, interceptor: suspend PipelineContext<Unit, ApplicationCall>.() -> Unit): Route {
- val subRoute = createChild(object : RouteSelector() {
- override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation =
- RouteSelectorEvaluation.Constant
- })
- subRoute.intercept(ApplicationCallPipeline.Plugins) {
- interceptor()
- proceed()
- }
-
- callback(subRoute)
- return subRoute
-}
/**
* This function tries to authenticate the call according
* to the scheme that is mentioned in the Authorization header.
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
@@ -466,7 +466,7 @@ private fun Routing.coreBankWithdrawalApi(db: Database, ctx: BankConfig) {
}
}
-private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) {
+private fun Routing.coreBankCashoutApi(db: Database, ctx: BankConfig) = conditional(ctx.haveCashout) {
val TAN_RETRY_COUNTER: Int = 3;
val TAN_VALIDITY_PERIOD: Duration = Duration.ofHours(1)
val TAN_RETRANSMISSION_PERIOD: Duration = Duration.ofMinutes(1)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -24,7 +24,12 @@ import io.ktor.server.application.*
import io.ktor.server.plugins.*
import io.ktor.server.request.*
import io.ktor.server.util.*
+import io.ktor.server.routing.Route
+import io.ktor.server.routing.RouteSelector
+import io.ktor.server.routing.RoutingResolveContext
+import io.ktor.server.routing.RouteSelectorEvaluation
import io.ktor.util.valuesOf
+import io.ktor.util.pipeline.PipelineContext
import net.taler.common.errorcodes.TalerErrorCode
import net.taler.wallet.crypto.Base32Crockford
import org.slf4j.Logger
@@ -156,4 +161,25 @@ suspend fun maybeCreateAdminAccount(db: Database, ctx: BankConfig, pw: String? =
CustomerCreationResult.CONFLICT_PAY_TO -> false
CustomerCreationResult.SUCCESS -> true
}
-}
-\ No newline at end of file
+}
+
+fun Route.intercept(callback: Route.() -> Unit, interceptor: suspend PipelineContext<Unit, ApplicationCall>.() -> Unit): Route {
+ val subRoute = createChild(object : RouteSelector() {
+ override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation =
+ RouteSelectorEvaluation.Constant
+ })
+ subRoute.intercept(ApplicationCallPipeline.Plugins) {
+ interceptor()
+ proceed()
+ }
+
+ callback(subRoute)
+ return subRoute
+}
+
+fun Route.conditional(implemented: Boolean, callback: Route.() -> Unit): Route =
+ intercept(callback) {
+ if (!implemented) {
+ throw libeufinError(HttpStatusCode.NotImplemented, "API not implemented", TalerErrorCode.END)
+ }
+ }
+\ No newline at end of file
diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt
@@ -1505,6 +1505,9 @@ class CoreBankCashoutApiTest {
val resp = json<ConversionResponse>()
assertEquals(TalerAmount("FIAT:1.247"), resp.amount_credit)
}
+ // Not implemented (yet)
+ client.get("/cashout-rate?amount_credit=FIAT:1")
+ .assertNotImplemented()
// Too small
client.get("/cashout-rate?amount_debit=KUDOS:0.08")
@@ -1539,6 +1542,9 @@ class CoreBankCashoutApiTest {
assertEquals(TalerAmount("KUDOS:$converted"), resp.amount_credit)
}
}
+ // Not implemented (yet)
+ client.get("/cashin-rate?amount_credit=KUDOS:1")
+ .assertNotImplemented()
// No amount
client.get("/cashin-rate")
@@ -1557,4 +1563,14 @@ class CoreBankCashoutApiTest {
client.get("/cashin-rate?amount_credit=FIAT:1")
.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH)
}
+
+ @Test
+ fun notImplemented() = bankSetup("test_restrict.conf") { _ ->
+ client.get("/cashin-rate")
+ .assertNotImplemented()
+ client.get("/cashout-rate")
+ .assertNotImplemented()
+ client.get("/accounts/customer/cashouts")
+ .assertNotImplemented()
+ }
}
\ No newline at end of file
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
@@ -185,6 +185,8 @@ suspend fun HttpResponse.assertBadRequest(err: TalerErrorCode? = null): HttpResp
= assertStatus(HttpStatusCode.BadRequest, err)
suspend fun HttpResponse.assertForbidden(err: TalerErrorCode? = null): HttpResponse
= assertStatus(HttpStatusCode.Forbidden, err)
+suspend fun HttpResponse.assertNotImplemented(err: TalerErrorCode? = null): HttpResponse
+ = assertStatus(HttpStatusCode.NotImplemented, err)
suspend fun HttpResponse.assertErr(code: TalerErrorCode): HttpResponse {