summaryrefslogtreecommitdiff
path: root/bank/src/test/kotlin/helpers.kt
diff options
context:
space:
mode:
Diffstat (limited to 'bank/src/test/kotlin/helpers.kt')
-rw-r--r--bank/src/test/kotlin/helpers.kt109
1 files changed, 91 insertions, 18 deletions
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
index c35dc721..951d24f5 100644
--- a/bank/src/test/kotlin/helpers.kt
+++ b/bank/src/test/kotlin/helpers.kt
@@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream
import java.io.File
import java.util.zip.DeflaterOutputStream
import kotlin.test.*
+import kotlin.random.Random
import kotlinx.coroutines.*
import kotlinx.serialization.json.*
import net.taler.common.errorcodes.TalerErrorCode
@@ -40,13 +41,19 @@ import tech.libeufin.util.*
val merchantPayto = IbanPayTo(genIbanPaytoUri())
val exchangePayto = IbanPayTo(genIbanPaytoUri())
val customerPayto = IbanPayTo(genIbanPaytoUri())
-val unknownPayto = IbanPayTo(genIbanPaytoUri())
+val unknownPayto = IbanPayTo(genIbanPaytoUri())
+var tmpPayTo = IbanPayTo(genIbanPaytoUri())
val paytos = mapOf(
"merchant" to merchantPayto,
"exchange" to exchangePayto,
"customer" to customerPayto
)
+fun genTmpPayTo(): IbanPayTo {
+ tmpPayTo = IbanPayTo(genIbanPaytoUri())
+ return tmpPayTo
+}
+
fun setup(
conf: String = "test.conf",
lambda: suspend (Database, BankConfig) -> Unit
@@ -85,7 +92,11 @@ fun bankSetup(
isTalerExchange = false,
isPublic = false,
bonus = bonus,
- checkPaytoIdempotent = false
+ checkPaytoIdempotent = false,
+ email = null,
+ phone = null,
+ cashoutPayto = null,
+ tanChannel = null
))
assertEquals(AccountCreationResult.Success, db.account.create(
login = "exchange",
@@ -96,7 +107,11 @@ fun bankSetup(
isTalerExchange = true,
isPublic = false,
bonus = bonus,
- checkPaytoIdempotent = false
+ checkPaytoIdempotent = false,
+ email = null,
+ phone = null,
+ cashoutPayto = null,
+ tanChannel = null
))
assertEquals(AccountCreationResult.Success, db.account.create(
login = "customer",
@@ -107,7 +122,11 @@ fun bankSetup(
isTalerExchange = false,
isPublic = false,
bonus = bonus,
- checkPaytoIdempotent = false
+ checkPaytoIdempotent = false,
+ email = null,
+ phone = null,
+ cashoutPayto = null,
+ tanChannel = null
))
// Create admin account
assertEquals(AccountCreationResult.Success, maybeCreateAdminAccount(db, ctx, "admin-password"))
@@ -163,20 +182,30 @@ suspend fun ApplicationTestBuilder.assertBalance(account: String, amount: String
}
}
+/** Check [account] tan channel and info */
+suspend fun ApplicationTestBuilder.tanInfo(account: String): Pair<TanChannel?, String?> {
+ val res = client.getA("/accounts/$account").assertOkJson<AccountData>()
+ val channel: TanChannel? = res.tan_channel
+ return Pair(channel, when (channel) {
+ TanChannel.sms -> res.contact_data!!.phone.get()
+ TanChannel.email -> res.contact_data!!.email.get()
+ null -> null
+ else -> null
+ })
+}
+
/** Perform a bank transaction of [amount] [from] account [to] account with [subject} */
suspend fun ApplicationTestBuilder.tx(from: String, amount: String, to: String, subject: String = "payout"): Long {
- return client.post("/accounts/$from/transactions") {
- basicAuth("$from", "$from-password")
+ return client.postA("/accounts/$from/transactions") {
json {
- "payto_uri" to "${paytos[to]}?message=${subject.encodeURLQueryComponent()}&amount=$amount"
+ "payto_uri" to "${paytos[to] ?: tmpPayTo}?message=${subject.encodeURLQueryComponent()}&amount=$amount"
}
- }.assertOkJson<TransactionCreateResponse>().row_id
+ }.maybeChallenge().assertOkJson<TransactionCreateResponse>().row_id
}
/** Perform a taler outgoing transaction of [amount] from exchange to merchant */
suspend fun ApplicationTestBuilder.transfer(amount: String) {
- client.post("/accounts/exchange/taler-wire-gateway/transfer") {
- pwAuth("exchange")
+ client.postA("/accounts/exchange/taler-wire-gateway/transfer") {
json {
"request_uid" to randHashCode()
"amount" to TalerAmount(amount)
@@ -220,11 +249,7 @@ suspend fun ApplicationTestBuilder.cashout(amount: String) {
}
} else {
res
- }.assertOkJson<CashoutPending> {
- client.postA("/accounts/customer/cashouts/${it.cashout_id}/confirm") {
- json { "tan" to smsCode("+99") }
- }.assertNoContent()
- }
+ }.assertOk()
}
/** Perform a whithrawal operation of [amount] from customer */
@@ -234,7 +259,7 @@ suspend fun ApplicationTestBuilder.withdrawal(amount: String) {
}.assertOkJson<BankAccountCreateWithdrawalResponse> {
val uuid = it.taler_withdraw_uri.split("/").last()
withdrawalSelect(uuid)
- client.postA("/withdrawals/${uuid}/confirm")
+ client.postA("/accounts/merchant/withdrawals/${uuid}/confirm")
.assertNoContent()
}
}
@@ -251,6 +276,18 @@ suspend fun ApplicationTestBuilder.fillCashoutInfo(account: String) {
}.assertNoContent()
}
+suspend fun ApplicationTestBuilder.fillTanInfo(account: String) {
+ client.patch("/accounts/$account") {
+ pwAuth("admin")
+ json {
+ "contact_data" to obj {
+ "phone" to "+${Random.nextInt(0, 10000)}"
+ }
+ "tan_channel" to "sms"
+ }
+ }.assertNoContent()
+}
+
suspend fun ApplicationTestBuilder.withdrawalSelect(uuid: String) {
client.post("/taler-integration/withdrawal-operation/$uuid") {
json {
@@ -265,7 +302,7 @@ suspend fun ApplicationTestBuilder.convert(amount: String): TalerAmount {
.assertOkJson<ConversionResponse>().amount_credit
}
-suspend fun smsCode(info: String): String? {
+suspend fun tanCode(info: String): String? {
val file = File("/tmp/tan-$info.txt");
if (file.exists()) {
val code = file.readText()
@@ -280,7 +317,7 @@ suspend fun smsCode(info: String): String? {
/* ----- Assert ----- */
suspend fun HttpResponse.assertStatus(status: HttpStatusCode, err: TalerErrorCode?): HttpResponse {
- assertEquals(status, this.status);
+ assertEquals(status, this.status, "$err")
if (err != null) assertErr(err)
return this
}
@@ -288,6 +325,8 @@ suspend fun HttpResponse.assertOk(): HttpResponse
= assertStatus(HttpStatusCode.OK, null)
suspend fun HttpResponse.assertNoContent(): HttpResponse
= assertStatus(HttpStatusCode.NoContent, null)
+suspend fun HttpResponse.assertAccepted(): HttpResponse
+ = assertStatus(HttpStatusCode.Accepted, null)
suspend fun HttpResponse.assertNotFound(err: TalerErrorCode?): HttpResponse
= assertStatus(HttpStatusCode.NotFound, err)
suspend fun HttpResponse.assertUnauthorized(): HttpResponse
@@ -308,6 +347,33 @@ suspend fun HttpResponse.assertErr(code: TalerErrorCode): HttpResponse {
return this
}
+suspend fun HttpResponse.maybeChallenge(): HttpResponse {
+ return if (this.status == HttpStatusCode.Accepted) {
+ this.assertChallenge()
+ } else {
+ this
+ }
+}
+
+suspend fun HttpResponse.assertChallenge(
+ check: suspend (TanChannel, String) -> Unit = { _, _ -> }
+): HttpResponse {
+ val id = assertAcceptedJson<TanChallenge>().challenge_id
+ val username = call.request.url.pathSegments[2]
+ val res = call.client.postA("/accounts/$username/challenge/$id").assertOkJson<TanTransmission>()
+ check(res.tan_channel, res.tan_info)
+ val code = tanCode(res.tan_info)
+ assertNotNull(code)
+ call.client.postA("/accounts/$username/challenge/$id/confirm") {
+ json { "tan" to code }
+ }.assertNoContent()
+ return call.client.request(this.call.request.url) {
+ pwAuth(username)
+ method = call.request.method
+ headers["X-Challenge-Id"] = "$id"
+ }
+}
+
suspend fun assertTime(min: Int, max: Int, lambda: suspend () -> Unit) {
val start = System.currentTimeMillis()
lambda()
@@ -360,6 +426,13 @@ inline suspend fun <reified B> HttpResponse.assertOkJson(lambda: (B) -> Unit = {
return body
}
+inline suspend fun <reified B> HttpResponse.assertAcceptedJson(lambda: (B) -> Unit = {}): B {
+ assertAccepted()
+ val body = json<B>()
+ lambda(body)
+ return body
+}
+
/* ----- Auth ----- */
/** Auto auth get request */