summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2023-10-16 14:08:23 +0000
committerAntoine A <>2023-10-16 14:08:23 +0000
commit69823ff11447df39ceeca879721a25153f840822 (patch)
tree73373f9c3190d3bfb279577851ffa6cc07eca460
parentdc895a89e77636bb46964ffbfd2d4d9194c6f286 (diff)
downloadlibeufin-69823ff11447df39ceeca879721a25153f840822.tar.gz
libeufin-69823ff11447df39ceeca879721a25153f840822.tar.bz2
libeufin-69823ff11447df39ceeca879721a25153f840822.zip
Improve and fix transactions endpoints
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt95
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/Main.kt2
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt25
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/helpers.kt17
-rw-r--r--bank/src/test/kotlin/CoreBankApiTest.kt292
-rw-r--r--bank/src/test/kotlin/WireGatewayApiTest.kt26
6 files changed, 300 insertions, 157 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
index 220ad654..459c662e 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt
@@ -479,26 +479,49 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) {
}
return@post
}
- // TRANSACTION ENDPOINT
+}
+
+fun Routing.coreBankTransactionsApi(db: Database, ctx: BankApplicationContext) {
get("/accounts/{USERNAME}/transactions") {
- val c = call.authenticateBankRequest(db, TokenScope.readonly) ?: throw unauthorized()
- val resourceName = call.getResourceName("USERNAME")
- if (!resourceName.canI(c, withAdmin = true)) throw forbidden()
- val historyParams = getHistoryParams(call.request.queryParameters)
- val resourceCustomer = db.customerGetFromLogin(resourceName) ?: throw notFound(
- hint = "Customer '$resourceName' not found in the database",
- talerEc = TalerErrorCode.TALER_EC_END // FIXME: need EC.
- )
- val bankAccount = db.bankAccountGetFromOwnerId(resourceCustomer.expectRowId())
- ?: throw internalServerError("Customer '${resourceCustomer.login}' lacks bank account.")
- val history: List<BankAccountTransactionInfo> = db.bankPoolHistory(historyParams, bankAccount.expectRowId())
+ val username = call.authCheck(db, TokenScope.readonly, true)
+ val params = getHistoryParams(call.request.queryParameters)
+ val bankAccount = call.bankAccount(db)
+
+ val history: List<BankAccountTransactionInfo> = db.bankPoolHistory(params, bankAccount.id)
call.respond(BankAccountTransactionsResponse(history))
}
- // Creates a bank transaction.
+ get("/accounts/{USERNAME}/transactions/{T_ID}") {
+ val username = call.authCheck(db, TokenScope.readonly, true)
+ val tId = call.expectUriComponent("T_ID")
+ val txRowId = try {
+ tId.toLong()
+ } catch (e: Exception) {
+ logger.error(e.message)
+ throw badRequest("TRANSACTION_ID is not a number: ${tId}")
+ }
+
+ val bankAccount = call.bankAccount(db)
+ val tx = db.bankTransactionGetFromInternalId(txRowId) ?: throw notFound(
+ "Bank transaction '$tId' not found",
+ TalerErrorCode.TALER_EC_BANK_TRANSACTION_NOT_FOUND
+ )
+ if (tx.bankAccountId != bankAccount.id) // TODO not found ?
+ throw unauthorized("Client has no rights over the bank transaction: $tId")
+
+ call.respond(
+ BankAccountTransactionInfo(
+ amount = tx.amount,
+ creditor_payto_uri = tx.creditorPaytoUri,
+ debtor_payto_uri = tx.debtorPaytoUri,
+ date = TalerProtocolTimestamp(tx.transactionDate),
+ direction = tx.direction,
+ subject = tx.subject,
+ row_id = txRowId
+ )
+ )
+ }
post("/accounts/{USERNAME}/transactions") {
- val c: Customer = call.authenticateBankRequest(db, TokenScope.readwrite) ?: throw unauthorized()
- val resourceName = call.expectUriComponent("USERNAME") // admin has no rights here.
- if ((c.login != resourceName) && (call.getAuthToken() == null)) throw forbidden()
+ val username = call.authCheck(db, TokenScope.readonly, false)
val tx = call.receive<BankAccountTransactionCreate>()
val subject = tx.payto_uri.message ?: throw badRequest("Wire transfer lacks subject")
@@ -509,15 +532,14 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) {
talerErrorCode = TalerErrorCode.TALER_EC_GENERIC_CURRENCY_MISMATCH
)
// TODO rewrite all thos database query in a single database function
- val debtorBankAccount = db.bankAccountGetFromOwnerId(c.expectRowId())
- ?: throw internalServerError("Debtor bank account not found")
+ val debtorBankAccount = call.bankAccount(db)
val creditorBankAccount = db.bankAccountGetFromInternalPayto(tx.payto_uri)
?: throw notFound(
"Creditor account not found",
TalerErrorCode.TALER_EC_BANK_UNKNOWN_ACCOUNT
)
val dbInstructions = BankInternalTransaction(
- debtorAccountId = debtorBankAccount.expectRowId(),
+ debtorAccountId = debtorBankAccount.id,
creditorAccountId = creditorBankAccount.expectRowId(),
subject = subject,
amount = amount,
@@ -537,39 +559,4 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) {
BankTransactionResult.SUCCESS -> call.respond(HttpStatusCode.OK)
}
}
- get("/accounts/{USERNAME}/transactions/{T_ID}") {
- val c = call.authenticateBankRequest(db, TokenScope.readonly) ?: throw unauthorized()
- val accountName = call.getResourceName("USERNAME")
- if (!accountName.canI(c, withAdmin = true)) throw forbidden()
- val tId = call.expectUriComponent("T_ID")
- val txRowId = try {
- tId.toLong()
- } catch (e: Exception) {
- logger.error(e.message)
- throw badRequest("TRANSACTION_ID is not a number: ${tId}")
- }
- val tx = db.bankTransactionGetFromInternalId(txRowId) ?: throw notFound(
- "Bank transaction '$tId' not found",
- TalerErrorCode.TALER_EC_BANK_TRANSACTION_NOT_FOUND
- )
- val accountCustomer = db.customerGetFromLogin(accountName) ?: throw notFound(
- hint = "Customer $accountName not found",
- talerEc = TalerErrorCode.TALER_EC_END // FIXME: need EC.
- )
- val customerBankAccount = db.bankAccountGetFromOwnerId(accountCustomer.expectRowId())
- ?: throw internalServerError("Customer '${accountCustomer.login}' lacks bank account.")
- if (tx.bankAccountId != customerBankAccount.bankAccountId) throw forbidden("Client has no rights over the bank transaction: $tId")
- call.respond(
- BankAccountTransactionInfo(
- amount = tx.amount,
- creditor_payto_uri = tx.creditorPaytoUri,
- debtor_payto_uri = tx.debtorPaytoUri,
- date = TalerProtocolTimestamp(tx.transactionDate),
- direction = tx.direction,
- subject = tx.subject,
- row_id = txRowId
- )
- )
- return@get
- }
} \ No newline at end of file
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
index 5e21826a..c09a15b4 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -260,6 +260,8 @@ fun Application.corebankWebApp(db: Database, ctx: BankApplicationContext) {
return@get
}
this.accountsMgmtApi(db, ctx)
+ this.coreBankTransactionsApi(db, ctx)
+ this.accountsMgmtApi(db, ctx)
this.bankIntegrationApi(db, ctx)
this.wireGatewayApi(db, ctx)
}
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
index 9b0f6d64..657ce0f1 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt
@@ -37,30 +37,13 @@ import kotlin.math.abs
private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.nexus")
fun Routing.wireGatewayApi(db: Database, ctx: BankApplicationContext) {
- /** Authenticate and check access rights */
- suspend fun ApplicationCall.authCheck(scope: TokenScope, withAdmin: Boolean): String {
- val authCustomer = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login")
- val username = getResourceName("USERNAME")
- if (!username.canI(authCustomer, withAdmin)) throw unauthorized("No right on $username account")
- return username
- }
-
- /** Retrieve the bank account info for the selected username*/
- suspend fun ApplicationCall.bankAccount(): Database.BankInfo {
- val username = getResourceName("USERNAME")
- return db.bankAccountInfoFromCustomerLogin(username) ?: throw notFound(
- hint = "Customer $username not found",
- talerEc = TalerErrorCode.TALER_EC_END // FIXME: need EC.
- )
- }
-
get("/taler-wire-gateway/config") {
call.respond(TWGConfigResponse(currency = ctx.currency))
return@get
}
post("/accounts/{USERNAME}/taler-wire-gateway/transfer") {
- val username = call.authCheck(TokenScope.readwrite, true)
+ val username = call.authCheck(db, TokenScope.readwrite, true)
val req = call.receive<TransferRequest>()
if (req.amount.currency != ctx.currency)
throw badRequest(
@@ -115,9 +98,9 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankApplicationContext) {
reduce: (List<T>, String) -> Any,
dbLambda: suspend Database.(HistoryParams, Long) -> List<T>
) {
- val username = call.authCheck(TokenScope.readonly, true)
+ val username = call.authCheck(db, TokenScope.readonly, true)
val params = getHistoryParams(call.request.queryParameters)
- val bankAccount = call.bankAccount()
+ val bankAccount = call.bankAccount(db)
if (!bankAccount.isTalerExchange)
throw conflict(
@@ -143,7 +126,7 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankApplicationContext) {
}
post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-incoming") {
- val username = call.authCheck(TokenScope.readwrite, false)
+ val username = call.authCheck(db, TokenScope.readwrite, false)
val req = call.receive<AddIncomingRequest>()
if (req.amount.currency != ctx.currency)
throw badRequest(
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
index 653f8bd8..8f2c56c0 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt
@@ -54,6 +54,23 @@ fun ApplicationCall.getAuthToken(): String? {
return null // Not a Bearer token case.
}
+/** Authenticate and check access rights */
+suspend fun ApplicationCall.authCheck(db: Database, scope: TokenScope, withAdmin: Boolean): String {
+ val authCustomer = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login")
+ val username = getResourceName("USERNAME")
+ if (!username.canI(authCustomer, withAdmin)) throw unauthorized("No right on $username account")
+ return username
+}
+
+/** Retrieve the bank account info for the selected username*/
+suspend fun ApplicationCall.bankAccount(db: Database): Database.BankInfo {
+ val username = getResourceName("USERNAME")
+ return db.bankAccountInfoFromCustomerLogin(username) ?: throw notFound(
+ hint = "Customer $username not found",
+ talerEc = TalerErrorCode.TALER_EC_END // FIXME: need EC.
+ )
+}
+
/**
* Performs the HTTP basic authentication. Returns the
* authenticated customer on success, or null otherwise.
diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt
index ea8cc055..2af6ecbd 100644
--- a/bank/src/test/kotlin/CoreBankApiTest.kt
+++ b/bank/src/test/kotlin/CoreBankApiTest.kt
@@ -1,6 +1,7 @@
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
+import io.ktor.client.HttpClient
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.engine.*
@@ -17,91 +18,207 @@ import java.time.Duration
import java.time.Instant
import java.time.temporal.ChronoUnit
import kotlin.random.Random
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
-import kotlin.test.assertNotNull
+import kotlin.test.*
+import kotlinx.coroutines.*
-class LibeuFinApiTest {
- private val customerFoo = Customer(
- login = "foo",
- passwordHash = CryptoUtil.hashpw("pw"),
- name = "Foo",
- phone = "+00",
- email = "foo@b.ar",
- cashoutPayto = "payto://external-IBAN",
- cashoutCurrency = "KUDOS"
- )
- private val customerBar = Customer(
- login = "bar",
- passwordHash = CryptoUtil.hashpw("pw"),
- name = "Bar",
- phone = "+99",
- email = "bar@example.com",
- cashoutPayto = "payto://external-IBAN",
- cashoutCurrency = "KUDOS"
- )
+class CoreBankTransactionsApiTest {
+ // Test endpoint is correctly authenticated
+ suspend fun ApplicationTestBuilder.authRoutine(path: String, withAdmin: Boolean = true, method: HttpMethod = HttpMethod.Post) {
+ // No body when authentication must happen before parsing the body
+
+ // Unknown account
+ client.request(path) {
+ this.method = method
+ basicAuth("unknown", "password")
+ }.assertStatus(HttpStatusCode.Unauthorized)
- private fun genBankAccount(rowId: Long) = BankAccount(
- hasDebt = false,
- internalPaytoUri = IbanPayTo("payto://iban/ac${rowId}"),
- maxDebt = TalerAmount(100, 0, "KUDOS"),
- owningCustomerId = rowId
- )
+ // Wrong password
+ client.request(path) {
+ this.method = method
+ basicAuth("merchant", "wrong-password")
+ }.assertStatus(HttpStatusCode.Unauthorized)
- @Test
- fun getConfig() = bankSetup { _ ->
- val r = client.get("/config") {
- expectSuccess = true
- }.assertOk()
- println(r.bodyAsText())
+ // Wrong account
+ client.request(path) {
+ this.method = method
+ basicAuth("exchange", "merchant-password")
+ }.assertStatus(HttpStatusCode.Unauthorized)
+
+ // TODO check admin rights
}
- /**
- * Testing GET /transactions. This test checks that the sign
- * of delta gets honored by the HTTP handler, namely that the
- * records appear in ASC or DESC order, according to the sign
- * of delta.
- */
+ // GET /transactions
@Test
- fun testHistory() = setup { db, ctx ->
- // TODO add better tests with lon polling like Wire Gateway API
- val fooId = db.customerCreate(customerFoo); assert(fooId != null)
- assert(db.bankAccountCreate(genBankAccount(fooId!!)) != null)
- val barId = db.customerCreate(customerBar); assert(barId != null)
- assert(db.bankAccountCreate(genBankAccount(barId!!)) != null)
- for (i in 1..10) {
- db.bankTransactionCreate(genTx("test-$i"))
- }
- testApplication {
- application {
- corebankWebApp(db, ctx)
- }
- val asc = client.get("/accounts/foo/transactions?delta=2") {
- basicAuth("foo", "pw")
- expectSuccess = true
- }
- var obj = Json.decodeFromString<BankAccountTransactionsResponse>(asc.bodyAsText())
- assert(obj.transactions.size == 2)
- assert(obj.transactions[0].row_id < obj.transactions[1].row_id)
- val desc = client.get("/accounts/foo/transactions?delta=-2") {
- basicAuth("foo", "pw")
- expectSuccess = true
+ fun testHistory() = bankSetup { _ ->
+ suspend fun HttpResponse.assertHistory(size: Int) {
+ assertOk()
+ val txt = this.bodyAsText()
+ val history = Json.decodeFromString<BankAccountTransactionsResponse>(txt)
+ val params = getHistoryParams(this.call.request.url.parameters)
+
+ // testing the size is like expected.
+ assert(history.transactions.size == size) {
+ println("transactions has wrong size: ${history.transactions.size}")
+ println("Response was: ${txt}")
+ }
+ if (size > 0) {
+ if (params.delta < 0) {
+ // testing that the first row_id is at most the 'start' query param.
+ assert(history.transactions[0].row_id <= params.start)
+ // testing that the row_id decreases.
+ assert(history.transactions.windowed(2).all { (a, b) -> a.row_id > b.row_id })
+ } else {
+ // testing that the first row_id is at least the 'start' query param.
+ assert(history.transactions[0].row_id >= params.start)
+ // testing that the row_id increases.
+ assert(history.transactions.windowed(2).all { (a, b) -> a.row_id < b.row_id })
+ }
}
- obj = Json.decodeFromString(desc.bodyAsText())
- assert(obj.transactions.size == 2)
- assert(obj.transactions[0].row_id > obj.transactions[1].row_id)
}
+
+ authRoutine("/accounts/merchant/transactions?delta=7", method = HttpMethod.Get)
+
+ // Check empty lisy when no transactions
+ client.get("/accounts/merchant/transactions?delta=7") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(0)
+
+ // Gen three transactions from merchant to exchange
+ repeat(3) {
+ client.post("/accounts/merchant/transactions") {
+ basicAuth("merchant", "merchant-password")
+ jsonBody(json {
+ "payto_uri" to "payto://iban/EXCHANGE-IBAN-XYZ?message=payout$it&amount=KUDOS:0.$it"
+ })
+ }.assertOk()
+ }
+ // Gen two transactions from exchange to merchant
+ repeat(2) {
+ client.post("/accounts/exchange/transactions") {
+ basicAuth("exchange", "exchange-password")
+ jsonBody(json {
+ "payto_uri" to "payto://iban/MERCHANT-IBAN-XYZ?message=payout$it&amount=KUDOS:0.$it"
+ })
+ }.assertOk()
+ }
+
+ // Check no useless polling
+ assertTime(0, 300) {
+ client.get("/accounts/merchant/transactions?delta=-6&start=11&long_poll_ms=1000") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(5)
+ }
+
+ // Check polling end
+ client.get("/accounts/merchant/transactions?delta=6&long_poll_ms=60") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(5)
+
+ runBlocking {
+ joinAll(
+ launch { // Check polling succeed forward
+ assertTime(200, 1000) {
+ client.get("/accounts/merchant/transactions?delta=6&long_poll_ms=1000") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(6)
+ }
+ },
+ launch { // Check polling succeed backward
+ assertTime(200, 1000) {
+ client.get("/accounts/merchant/transactions?delta=-6&long_poll_ms=1000") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(6)
+ }
+ },
+ launch { // Check polling timeout forward
+ assertTime(200, 400) {
+ client.get("/accounts/merchant/transactions?delta=8&long_poll_ms=300") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(6)
+ }
+ },
+ launch { // Check polling timeout backward
+ assertTime(200, 400) {
+ client.get("/accounts/merchant/transactions?delta=-8&long_poll_ms=300") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(6)
+ }
+ },
+ launch {
+ delay(200)
+ client.post("/accounts/merchant/transactions") {
+ basicAuth("merchant", "merchant-password")
+ jsonBody(json {
+ "payto_uri" to "payto://iban/EXCHANGE-IBAN-XYZ?message=payout_poll&amount=KUDOS:4.2"
+ })
+ }.assertOk()
+ }
+ )
+ }
+
+ // Testing ranges.
+ repeat(30) {
+ client.post("/accounts/merchant/transactions") {
+ basicAuth("merchant", "merchant-password")
+ jsonBody(json {
+ "payto_uri" to "payto://iban/EXCHANGE-IBAN-XYZ?message=payout_range&amount=KUDOS:0.001"
+ })
+ }.assertOk()
+ }
+
+ // forward range:
+ client.get("/accounts/merchant/transactions?delta=10&start=20") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(10)
+
+ // backward range:
+ client.get("/accounts/merchant/transactions?delta=-10&start=25") {
+ basicAuth("merchant", "merchant-password")
+ }.assertHistory(10)
+ }
+
+ // GET /transactions/T_ID
+ @Test
+ fun testById() = bankSetup { _ ->
+ authRoutine("/accounts/merchant/transactions/1", method = HttpMethod.Get)
+
+ // Create transaction
+ client.post("/accounts/merchant/transactions") {
+ basicAuth("merchant", "merchant-password")
+ jsonBody(json {
+ "payto_uri" to "payto://iban/EXCHANGE-IBAN-XYZ?message=payout"
+ "amount" to "KUDOS:0.3"
+ })
+ }.assertOk()
+ // Check OK
+ client.get("/accounts/merchant/transactions/1") {
+ basicAuth("merchant", "merchant-password")
+ }.assertOk().run {
+ val tx: BankAccountTransactionInfo = Json.decodeFromString(bodyAsText())
+ assertEquals("payout", tx.subject)
+ assertEquals(TalerAmount("KUDOS:0.3"), tx.amount)
+ }
+ // Check unknown transaction
+ client.get("/accounts/merchant/transactions/3") {
+ basicAuth("merchant", "merchant-password")
+ }.assertStatus(HttpStatusCode.NotFound)
+ // Check wrong transaction
+ client.get("/accounts/merchant/transactions/2") {
+ basicAuth("merchant", "merchant-password")
+ }.assertStatus(HttpStatusCode.Unauthorized) // Should be NOT_FOUND ?
}
- // Testing the creation of bank transactions.
+ // POST /transactions
@Test
- fun postTransactionsTest() = bankSetup { _ ->
+ fun testCreate() = bankSetup { _ ->
val valid_req = json {
"payto_uri" to "payto://iban/EXCHANGE-IBAN-XYZ?message=payout"
"amount" to "KUDOS:0.3"
}
- // Check ok
+ authRoutine("/accounts/merchant/transactions", withAdmin = false)
+
+ // Check OK
client.post("/accounts/merchant/transactions") {
basicAuth("merchant", "merchant-password")
jsonBody(valid_req)
@@ -182,6 +299,43 @@ class LibeuFinApiTest {
})
}.assertStatus(HttpStatusCode.Conflict)
}
+
+}
+
+class LibeuFinApiTest {
+ private val customerFoo = Customer(
+ login = "foo",
+ passwordHash = CryptoUtil.hashpw("pw"),
+ name = "Foo",
+ phone = "+00",
+ email = "foo@b.ar",
+ cashoutPayto = "payto://external-IBAN",
+ cashoutCurrency = "KUDOS"
+ )
+ private val customerBar = Customer(
+ login = "bar",
+ passwordHash = CryptoUtil.hashpw("pw"),
+ name = "Bar",
+ phone = "+99",
+ email = "bar@example.com",
+ cashoutPayto = "payto://external-IBAN",
+ cashoutCurrency = "KUDOS"
+ )
+
+ private fun genBankAccount(rowId: Long) = BankAccount(
+ hasDebt = false,
+ internalPaytoUri = IbanPayTo("payto://iban/ac${rowId}"),
+ maxDebt = TalerAmount(100, 0, "KUDOS"),
+ owningCustomerId = rowId
+ )
+
+ @Test
+ fun getConfig() = bankSetup { _ ->
+ val r = client.get("/config") {
+ expectSuccess = true
+ }.assertOk()
+ println(r.bodyAsText())
+ }
@Test
fun passwordChangeTest() = setup { db, ctx ->
diff --git a/bank/src/test/kotlin/WireGatewayApiTest.kt b/bank/src/test/kotlin/WireGatewayApiTest.kt
index 34b32296..a87d9ff0 100644
--- a/bank/src/test/kotlin/WireGatewayApiTest.kt
+++ b/bank/src/test/kotlin/WireGatewayApiTest.kt
@@ -47,7 +47,7 @@ class WireGatewayApiTest {
}
// Test endpoint is correctly authenticated
- suspend fun authRoutine(client: HttpClient, path: String, body: JsonObject? = null, method: HttpMethod = HttpMethod.Post) {
+ suspend fun ApplicationTestBuilder.authRoutine(path: String, body: JsonObject? = null, method: HttpMethod = HttpMethod.Post) {
// No body when authentication must happen before parsing the body
// Unknown account
@@ -87,7 +87,7 @@ class WireGatewayApiTest {
"credit_account" to "payto://iban/MERCHANT-IBAN-XYZ"
};
- authRoutine(client, "/accounts/merchant/taler-wire-gateway/transfer", valid_req)
+ authRoutine("/accounts/merchant/taler-wire-gateway/transfer", valid_req)
// Checking exchange debt constraint.
client.post("/accounts/exchange/taler-wire-gateway/transfer") {
@@ -223,7 +223,7 @@ class WireGatewayApiTest {
}
- authRoutine(client, "/accounts/merchant/taler-wire-gateway/history/incoming?delta=7", method = HttpMethod.Get)
+ authRoutine("/accounts/merchant/taler-wire-gateway/history/incoming?delta=7", method = HttpMethod.Get)
// Check error when no transactions
client.get("/accounts/exchange/taler-wire-gateway/history/incoming?delta=7") {
@@ -305,18 +305,18 @@ class WireGatewayApiTest {
}
// Testing ranges.
- repeat(300) {
+ repeat(20) {
db.genIncoming("exchange", bankAccountMerchant)
}
// forward range:
- client.get("/accounts/exchange/taler-wire-gateway/history/incoming?delta=10&start=30") {
- basicAuth("exchange", "exchange-password")
+ client.get("/accounts/exchange/taler-wire-gateway/history/incoming?delta=10&start=20") {
+ basicAuth("exchange", "exchange-password")
}.assertHistory(10)
// backward range:
- client.get("/accounts/exchange/taler-wire-gateway/history/incoming?delta=-10&start=300") {
- basicAuth("exchange", "exchange-password")
+ client.get("/accounts/exchange/taler-wire-gateway/history/incoming?delta=-10&start=25") {
+ basicAuth("exchange", "exchange-password")
}.assertHistory(10)
}
@@ -358,7 +358,7 @@ class WireGatewayApiTest {
}
}
- authRoutine(client, "/accounts/merchant/taler-wire-gateway/history/outgoing?delta=7", method = HttpMethod.Get)
+ authRoutine("/accounts/merchant/taler-wire-gateway/history/outgoing?delta=7", method = HttpMethod.Get)
// Check error when no transactions
client.get("/accounts/exchange/taler-wire-gateway/history/outgoing?delta=7") {
@@ -440,17 +440,17 @@ class WireGatewayApiTest {
}
// Testing ranges.
- repeat(300) {
+ repeat(20) {
db.genTransfer("exchange", bankAccountMerchant)
}
// forward range:
- client.get("/accounts/exchange/taler-wire-gateway/history/outgoing?delta=10&start=30") {
+ client.get("/accounts/exchange/taler-wire-gateway/history/outgoing?delta=10&start=20") {
basicAuth("exchange", "exchange-password")
}.assertHistory(10)
// backward range:
- client.get("/accounts/exchange/taler-wire-gateway/history/outgoing?delta=-10&start=300") {
+ client.get("/accounts/exchange/taler-wire-gateway/history/outgoing?delta=-10&start=25") {
basicAuth("exchange", "exchange-password")
}.assertHistory(10)
}
@@ -464,7 +464,7 @@ class WireGatewayApiTest {
"debit_account" to "payto://iban/MERCHANT-IBAN-XYZ"
};
- authRoutine(client, "/accounts/merchant/taler-wire-gateway/admin/add-incoming", valid_req)
+ authRoutine("/accounts/merchant/taler-wire-gateway/admin/add-incoming", valid_req)
// Checking exchange debt constraint.
client.post("/accounts/exchange/taler-wire-gateway/admin/add-incoming") {