libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 5c671b88781678b01937a3893438c97d6f2fd5dd
parent 5086e2514bc6f0881b630b20d07ce0737bc9fbea
Author: Antoine A <>
Date:   Tue, 17 Oct 2023 12:52:28 +0000

Cleanup

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/Authentication.kt | 85++++++++++++++++++++++++++++++++++++-------------------------------------------
Mbank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt | 8++------
Mbank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt | 43+++++++++++--------------------------------
Mbank/src/main/kotlin/tech/libeufin/bank/Database.kt | 168++++++++++++++-----------------------------------------------------------------
Mbank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt | 4++--
Mbank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 6+++---
Mbank/src/test/kotlin/CoreBankApiTest.kt | 4++--
Mbank/src/test/kotlin/DatabaseTest.kt | 22++++++++++++++--------
8 files changed, 103 insertions(+), 237 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt b/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt @@ -7,6 +7,33 @@ import tech.libeufin.util.* import net.taler.wallet.crypto.Base32Crockford import java.time.Instant +/** Authenticate admin */ +suspend fun ApplicationCall.authAdmin(db: Database, scope: TokenScope) { + // TODO when all endpoints use this function we can use an optimized database request that only query the customer login + val login = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login") + if (login != "admin") { + throw unauthorized("Only administrator allowed") + } +} + +/** Authenticate and check access rights */ +suspend fun ApplicationCall.authCheck(db: Database, scope: TokenScope, withAdmin: Boolean = true, requireAdmin: Boolean = false): Pair<String, Boolean> { + // TODO when all endpoints use this function we can use an optimized database request that only query the customer login + val authLogin = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login") + val login = accountLogin() + if (requireAdmin && authLogin != "admin") { + if (authLogin != "admin") { + throw unauthorized("Only administrator allowed") + } + } else { + val hasRight = authLogin == login || (withAdmin && authLogin == "admin"); + if (!hasRight) { + throw unauthorized("Customer $authLogin have no right on $login account") + } + } + return Pair(login, authLogin == "admin") +} + /** * This function tries to authenticate the call according * to the scheme that is mentioned in the Authorization header. @@ -14,9 +41,9 @@ import java.time.Instant * * requiredScope can be either "readonly" or "readwrite". * - * Returns the authenticated customer, or null if they failed. + * Returns the authenticated customer login, or null if they failed. */ -suspend fun ApplicationCall.authenticateBankRequest(db: Database, requiredScope: TokenScope): Customer? { +private suspend fun ApplicationCall.authenticateBankRequest(db: Database, requiredScope: TokenScope): String? { // Extracting the Authorization header. val header = getAuthorizationRawHeader(this.request) ?: throw badRequest( "Authorization header not found.", @@ -29,41 +56,8 @@ suspend fun ApplicationCall.authenticateBankRequest(db: Database, requiredScope: return when (authDetails.scheme) { "Basic" -> doBasicAuth(db, authDetails.content) "Bearer" -> doTokenAuth(db, authDetails.content, requiredScope) - else -> throw LibeufinBankException( - httpStatus = HttpStatusCode.Unauthorized, - talerError = TalerError( - code = TalerErrorCode.TALER_EC_GENERIC_UNAUTHORIZED.code, - hint = "Authorization method wrong or not supported." - ) - ) - } -} - -/** Authenticate admin */ -suspend fun ApplicationCall.authAdmin(db: Database, scope: TokenScope) { - // TODO when all endpoints use this function we can use an optimized database request that only query the customer login - val c = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login") - if (c.login != "admin") { - throw unauthorized("Only administrator allowed") - } -} - -/** Authenticate and check access rights */ -suspend fun ApplicationCall.authCheck(db: Database, scope: TokenScope, withAdmin: Boolean = true, requireAdmin: Boolean = false): Pair<String, Boolean> { - // TODO when all endpoints use this function we can use an optimized database request that only query the customer login - val c = authenticateBankRequest(db, scope) ?: throw unauthorized("Bad login") - val login = accountLogin() - if (requireAdmin && c.login != "admin") { - if (c.login != "admin") { - throw unauthorized("Only administrator allowed") - } - } else { - val hasRight = c.login == login || (withAdmin && c.login == "admin"); - if (!hasRight) { - throw unauthorized("No right on $login account") - } + else -> throw unauthorized("Authorization method wrong or not supported.") } - return Pair(login, c.login == "admin") } // Get the auth token (stripped of the bearer-token:-prefix) @@ -83,9 +77,9 @@ fun ApplicationCall.getAuthToken(): String? { /** * Performs the HTTP basic authentication. Returns the - * authenticated customer on success, or null otherwise. + * authenticated customer login on success, or null otherwise. */ -private suspend fun doBasicAuth(db: Database, encodedCredentials: String): Customer? { +private suspend fun doBasicAuth(db: Database, encodedCredentials: String): String? { val plainUserAndPass = String(base64ToBytes(encodedCredentials), Charsets.UTF_8) // :-separated val userAndPassSplit = plainUserAndPass.split( ":", @@ -102,11 +96,10 @@ private suspend fun doBasicAuth(db: Database, encodedCredentials: String): Custo "Malformed Basic auth credentials found in the Authorization header." ) ) - val login = userAndPassSplit[0] - val plainPassword = userAndPassSplit[1] - val maybeCustomer = db.customerGetFromLogin(login) ?: throw unauthorized() - if (!CryptoUtil.checkpw(plainPassword, maybeCustomer.passwordHash)) return null - return maybeCustomer + val (login, plainPassword) = userAndPassSplit + val passwordHash = db.customerPasswordHashFromLogin(login) ?: throw unauthorized() + if (!CryptoUtil.checkpw(plainPassword, passwordHash)) return null + return login } /** @@ -122,12 +115,12 @@ private fun splitBearerToken(tok: String): String? { } /* Performs the secret-token authentication. Returns the - * authenticated customer on success, null otherwise. */ + * authenticated customer login on success, null otherwise. */ private suspend fun doTokenAuth( db: Database, token: String, requiredScope: TokenScope, -): Customer? { +): String? { val bareToken = splitBearerToken(token) ?: throw badRequest( "Bearer token malformed", talerErrorCode = TalerErrorCode.TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED @@ -157,7 +150,7 @@ private suspend fun doTokenAuth( return null } // Getting the related username. - return db.customerGetFromRowId(maybeToken.bankCustomer) ?: throw LibeufinBankException( + return db.customerLoginFromId(maybeToken.bankCustomer) ?: throw LibeufinBankException( httpStatus = HttpStatusCode.InternalServerError, talerError = TalerError( code = TalerErrorCode.TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE.code, hint = "Customer not found, despite token mentions it.", diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt @@ -29,12 +29,10 @@ import net.taler.common.errorcodes.TalerErrorCode fun Routing.bankIntegrationApi(db: Database, ctx: BankApplicationContext) { get("/taler-integration/config") { - val internalCurrency: String = ctx.currency call.respond(TalerIntegrationConfigResponse( - currency = internalCurrency, + currency = ctx.currency, currency_specification = ctx.currencySpecification )) - return@get } // Note: wopid acts as an authentication token. @@ -60,7 +58,6 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankApplicationContext) { confirm_transfer_url = confirmUrl ) ) - return@get } post("/taler-integration/withdrawal-operation/{wopid}") { val wopid = call.expectUriComponent("wopid") @@ -73,7 +70,7 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankApplicationContext) { ) } val dbSuccess: Boolean = if (!op.selectionDone) { // Check if reserve pub. was used in _another_ withdrawal. - if (db.bankTransactionCheckExists(req.reserve_pub) != null) throw conflict( + if (db.bankTransactionCheckExists(req.reserve_pub)) throw conflict( "Reserve pub. already used", TalerErrorCode.TALER_EC_BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) db.talerWithdrawalSetDetails( @@ -96,6 +93,5 @@ fun Routing.bankIntegrationApi(db: Database, ctx: BankApplicationContext) { transfer_done = op.confirmationDone, confirm_transfer_url = confirmUrl ) call.respond(resp) - return@post } } \ No newline at end of file diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -26,14 +26,8 @@ private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.bank.account fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { // TOKEN ENDPOINTS delete("/accounts/{USERNAME}/token") { - val c = call.authenticateBankRequest(db, TokenScope.readonly) ?: throw unauthorized() + call.authCheck(db, TokenScope.readonly) val token = call.getAuthToken() ?: throw badRequest("Basic auth not supported here.") - val resourceName = call.getResourceName("USERNAME") - /** - * The following check makes sure that the token belongs - * to the username contained in {USERNAME}. - */ - if (!resourceName.canI(c, withAdmin = true)) throw forbidden() /** * Not sanity-checking the token, as it was used by the authentication already. @@ -49,13 +43,7 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { call.respond(HttpStatusCode.NoContent) } post("/accounts/{USERNAME}/token") { - val customer = - call.authenticateBankRequest(db, TokenScope.refreshable) ?: throw unauthorized("Authentication failed") - val endpointOwner = call.maybeUriComponent("USERNAME") - if (customer.login != endpointOwner) throw forbidden( - "User has no rights on this enpoint", - TalerErrorCode.TALER_EC_GENERIC_FORBIDDEN - ) + val (login, _) = call.authCheck(db, TokenScope.refreshable) val maybeAuthToken = call.getAuthToken() val req = call.receive<TokenRequest>() /** @@ -89,8 +77,8 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { throw badRequest("Bad token duration: ${e.message}") } } - val customerDbRow = customer.dbRowId ?: throw internalServerError( - "Could not get customer '${customer.login}' database row ID" + val customerDbRow = db.customerGetFromLogin(login)?.dbRowId ?: throw internalServerError( + "Could not get customer '$login' database row ID" ) val token = BearerToken( bankCustomer = customerDbRow, @@ -113,15 +101,13 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { } // WITHDRAWAL ENDPOINTS post("/accounts/{USERNAME}/withdrawals") { - val c = call.authenticateBankRequest(db, TokenScope.readwrite) - ?: throw unauthorized() // Admin not allowed to withdraw in the name of customers: - val accountName = call.expectUriComponent("USERNAME") - if (c.login != accountName) throw unauthorized("User ${c.login} not allowed to withdraw for account '${accountName}'") + call.authCheck(db, TokenScope.readwrite) val req = call.receive<BankAccountCreateWithdrawalRequest>() // Checking that the user has enough funds. - if(req.amount.currency != ctx.currency) + if (req.amount.currency != ctx.currency) throw badRequest("Wrong currency: ${req.amount.currency}") - val b = db.bankAccountGetFromOwnerId(c.expectRowId()) - ?: throw internalServerError("Customer '${c.login}' lacks bank account.") + val b = call.bankAccount(db) + + // TODO balance check only in database if (!isBalanceEnough( balance = b.expectBalance(), due = req.amount, maxDebt = b.maxDebt, hasBalanceDebt = b.hasDebt ) @@ -141,7 +127,6 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { withdrawal_id = opId.toString(), taler_withdraw_uri = getTalerWithdrawUri(bankBaseUrl, opId.toString()) ) ) - return@post } get("/withdrawals/{withdrawal_id}") { val op = getWithdrawal(db, call.expectUriComponent("withdrawal_id")) @@ -155,7 +140,6 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { selected_reserve_pub = op.reservePub ) ) - return@get } post("/withdrawals/{withdrawal_id}/abort") { val op = getWithdrawal(db, call.expectUriComponent("withdrawal_id")) // Idempotency: @@ -167,7 +151,6 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { hint = "Cannot abort confirmed withdrawal", talerEc = TalerErrorCode.TALER_EC_END ) call.respondText("{}", ContentType.Application.Json) - return@post } post("/withdrawals/{withdrawal_id}/confirm") { val op = getWithdrawal(db, call.expectUriComponent("withdrawal_id")) // Checking idempotency: @@ -198,7 +181,6 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { * find the withdrawal operation, that's on the bank. */ throw internalServerError("Withdrawal operation (${op.withdrawalUuid}) not found") - WithdrawalConfirmationResult.EXCHANGE_NOT_FOUND -> /** * That can happen because the bank did not check the exchange @@ -209,14 +191,11 @@ fun Routing.accountsMgmtApi(db: Database, ctx: BankApplicationContext) { hint = "Exchange to withdraw from not found", talerEc = TalerErrorCode.TALER_EC_BANK_UNKNOWN_ACCOUNT ) - WithdrawalConfirmationResult.CONFLICT -> throw internalServerError("Bank didn't check for idempotency") - WithdrawalConfirmationResult.SUCCESS -> call.respondText( "{}", ContentType.Application.Json ) } - return@post } } @@ -459,7 +438,7 @@ fun Routing.coreBankTransactionsApi(db: Database, ctx: BankApplicationContext) { val params = getHistoryParams(call.request.queryParameters) val bankAccount = call.bankAccount(db) - val history: List<BankAccountTransactionInfo> = db.bankPoolHistory(params, bankAccount.id) + val history: List<BankAccountTransactionInfo> = db.bankPoolHistory(params, bankAccount.bankAccountId!!) call.respond(BankAccountTransactionsResponse(history)) } get("/accounts/{USERNAME}/transactions/{T_ID}") { @@ -477,7 +456,7 @@ fun Routing.coreBankTransactionsApi(db: Database, ctx: BankApplicationContext) { "Bank transaction '$tId' not found", TalerErrorCode.TALER_EC_BANK_TRANSACTION_NOT_FOUND ) - if (tx.bankAccountId != bankAccount.id) // TODO not found ? + if (tx.bankAccountId != bankAccount.bankAccountId) // TODO not found ? throw unauthorized("Client has no rights over the bank transaction: $tId") call.respond( diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/Database.kt @@ -286,48 +286,39 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos } } - // Mostly used to get customers out of bearer tokens. - suspend fun customerGetFromRowId(customer_id: Long): Customer? = conn { conn -> + suspend fun customerChangePassword(customerName: String, passwordHash: String): Boolean = conn { conn -> val stmt = conn.prepareStatement(""" - SELECT - login, - password_hash, - name, - email, - phone, - cashout_payto, - cashout_currency - FROM customers - WHERE customer_id=? + UPDATE customers SET password_hash=? where login=? """) - stmt.setLong(1, customer_id) + stmt.setString(1, passwordHash) + stmt.setString(2, customerName) + stmt.executeUpdateCheck() + } + + suspend fun customerPasswordHashFromLogin(login: String): String? = conn { conn -> + val stmt = conn.prepareStatement(""" + SELECT password_hash FROM customers WHERE login=? + """) + stmt.setString(1, login) stmt.oneOrNull { - Customer( - login = it.getString("login"), - passwordHash = it.getString("password_hash"), - name = it.getString("name"), - phone = it.getString("phone"), - email = it.getString("email"), - cashoutCurrency = it.getString("cashout_currency"), - cashoutPayto = it.getString("cashout_payto"), - dbRowId = customer_id - ) + it.getString(1) } } - suspend fun customerChangePassword(customerName: String, passwordHash: String): Boolean = conn { conn -> + suspend fun customerLoginFromId(id: Long): String? = conn { conn -> val stmt = conn.prepareStatement(""" - UPDATE customers SET password_hash=? where login=? + SELECT login FROM customers WHERE customer_id=? """) - stmt.setString(1, passwordHash) - stmt.setString(2, customerName) - stmt.executeUpdateCheck() + stmt.setLong(1, id) + stmt.oneOrNull { + it.getString(1) + } } suspend fun customerGetFromLogin(login: String): Customer? = conn { conn -> val stmt = conn.prepareStatement(""" SELECT - customer_id, + customer_id, password_hash, name, email, @@ -656,38 +647,12 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos } } - data class BankInfo( - val id: Long, - val isTalerExchange: Boolean, - val internalPaytoUri: String - ) - - suspend fun bankAccountInfoFromCustomerLogin(login: String): BankInfo? = conn { conn -> - val stmt = conn.prepareStatement(""" - SELECT - bank_account_id - ,is_taler_exchange - ,internal_payto_uri - FROM bank_accounts - JOIN customers - ON customer_id=owning_customer_id - WHERE login=? - """) - stmt.setString(1, login) - stmt.oneOrNull { - BankInfo( - id = it.getLong(1), - isTalerExchange = it.getBoolean(2), - internalPaytoUri = it.getString(3), - ) - } - } - - suspend fun bankAccountGetFromInternalPayto(internalPayto: IbanPayTo): BankAccount? = conn { conn -> + suspend fun bankAccountGetFromCustomerLogin(login: String): BankAccount? = conn { conn -> val stmt = conn.prepareStatement(""" SELECT bank_account_id ,owning_customer_id + ,internal_payto_uri ,is_public ,is_taler_exchange ,last_nexus_fetch_row_id @@ -697,13 +662,15 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos ,(max_debt).val AS max_debt_val ,(max_debt).frac AS max_debt_frac FROM bank_accounts - WHERE internal_payto_uri=? + JOIN customers + ON customer_id=owning_customer_id + WHERE login=? """) - stmt.setString(1, internalPayto.canonical) + stmt.setString(1, login) stmt.oneOrNull { BankAccount( - internalPaytoUri = internalPayto, + internalPaytoUri = IbanPayTo(it.getString("internal_payto_uri")), balance = TalerAmount( it.getLong("balance_val"), it.getInt("balance_frac"), @@ -887,14 +854,14 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos * * Returns the row ID if found, null otherwise. */ - suspend fun bankTransactionCheckExists(subject: String): Long? = conn { conn -> + suspend fun bankTransactionCheckExists(subject: String): Boolean = conn { conn -> val stmt = conn.prepareStatement(""" - SELECT bank_transaction_id + SELECT 1 FROM bank_account_transactions WHERE subject = ?; """) stmt.setString(1, subject) - stmt.oneOrNull { it.getLong("bank_transaction_id") } + stmt.oneOrNull { } != null } // Get the bank transaction whose row ID is rowId @@ -1122,67 +1089,6 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos } } - /** - * The following function returns the list of transactions, according - * to the history parameters. The parameters take at least the 'start' - * and 'delta' values, and _optionally_ the payment direction. At the - * moment, only the TWG uses the direction, to provide the /incoming - * and /outgoing endpoints. - */ - suspend fun bankTransactionGetHistory( - start: Long, - delta: Int, - bankAccountId: Long - ): List<BankAccountTransaction> = conn { conn -> - val (cmpOp, orderBy) = if (delta < 0) Pair("<", "DESC") else Pair(">", "ASC") - val stmt = conn.prepareStatement(""" - SELECT - creditor_payto_uri - ,creditor_name - ,debtor_payto_uri - ,debtor_name - ,subject - ,(amount).val AS amount_val - ,(amount).frac AS amount_frac - ,transaction_date - ,account_servicer_reference - ,payment_information_id - ,end_to_end_id - ,direction - ,bank_account_id - ,bank_transaction_id - FROM bank_account_transactions - WHERE bank_transaction_id ${cmpOp} ? - AND bank_account_id=? - ORDER BY bank_transaction_id ${orderBy} - LIMIT ? - """) - stmt.setLong(1, start) - stmt.setLong(2, bankAccountId) - stmt.setInt(3, abs(delta)) - stmt.all { - BankAccountTransaction( - creditorPaytoUri = it.getString("creditor_payto_uri"), - creditorName = it.getString("creditor_name"), - debtorPaytoUri = it.getString("debtor_payto_uri"), - debtorName = it.getString("debtor_name"), - amount = TalerAmount( - it.getLong("amount_val"), - it.getInt("amount_frac"), - getCurrency() - ), - accountServicerReference = it.getString("account_servicer_reference"), - endToEndId = it.getString("end_to_end_id"), - direction = TransactionDirection.valueOf(it.getString("direction")), - bankAccountId = it.getLong("bank_account_id"), - paymentInformationId = it.getString("payment_information_id"), - subject = it.getString("subject"), - transactionDate = it.getLong("transaction_date").microsToJavaInstant() ?: throw faultyTimestampByBank(), - dbRowId = it.getLong("bank_transaction_id") - ) - } - } - // WITHDRAWALS suspend fun talerWithdrawalCreate( opUUID: UUID, @@ -1491,20 +1397,6 @@ class Database(dbConfig: String, private val bankCurrency: String): java.io.Clos } /** - * Represents the database row related to one payment - * that was requested by the Taler exchange. - */ - data class TalerTransferFromDb( - val timestamp: Long, - val debitTxRowId: Long, - val requestUid: HashCode, - val amount: TalerAmount, - val exchangeBaseUrl: String, - val wtid: ShortHashCode, - val creditAccount: String - ) - - /** * Holds the result of inserting a Taler transfer request * into the database. */ diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt @@ -108,12 +108,12 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankApplicationContext) { TalerErrorCode.TALER_EC_BANK_UNKNOWN_ACCOUNT ) - val items = db.dbLambda(params, bankAccount.id); + val items = db.dbLambda(params, bankAccount.bankAccountId!!); if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { - call.respond(reduce(items, bankAccount.internalPaytoUri)) + call.respond(reduce(items, bankAccount.internalPaytoUri.canonical)) } } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -69,10 +69,10 @@ fun ApplicationCall.getResourceName(param: String): ResourceName = suspend fun ApplicationCall.accountLogin(): String = getResourceName("USERNAME") /** Retrieve the bank account info for the selected username*/ -suspend fun ApplicationCall.bankAccount(db: Database): Database.BankInfo { +suspend fun ApplicationCall.bankAccount(db: Database): BankAccount { val login = accountLogin() - return db.bankAccountInfoFromCustomerLogin(login) ?: throw notFound( - hint = "Customer $login not found", + return db.bankAccountGetFromCustomerLogin(login) ?: throw notFound( + hint = "Bank account for customer $login not found", talerEc = TalerErrorCode.TALER_EC_BANK_UNKNOWN_ACCOUNT ) } diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -264,7 +264,7 @@ class CoreBankAccountsMgmtApiTest { // GET /accounts/USERNAME @Test - fun getAccountTest() = bankSetup { db -> + fun getAccountTest() = bankSetup { _ -> // Check ok client.get("/accounts/merchant") { basicAuth("merchant", "merchant-password") @@ -738,7 +738,7 @@ class LibeuFinApiTest { expectSuccess = false basicAuth("foo", "pw") } - assert(r.status == HttpStatusCode.Forbidden) + assert(r.status == HttpStatusCode.Unauthorized) // Make ad-hoc token for foo. val fooTok = ByteArray(32).apply { Random.nextBytes(this) } assert( diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt @@ -313,18 +313,24 @@ class DatabaseTest { // Foo pays Bar 100 times: for (i in 1..100) { db.bankTransactionCreate(genTx("test-$i")) } // Testing positive delta: - val forward = db.bankTransactionGetHistory( - start = 50L, - delta = 2, + val forward = db.bankPoolHistory( + params = HistoryParams( + start = 50L, + delta = 2, + poll_ms = 0 + ), bankAccountId = 1L // asking as Foo ) - assert(forward[0].expectRowId() >= 50 && forward.size == 2 && forward[0].dbRowId!! < forward[1].dbRowId!!) - val backward = db.bankTransactionGetHistory( - start = 50L, - delta = -2, + assert(forward[0].row_id >= 50 && forward.size == 2 && forward[0].row_id < forward[1].row_id) + val backward = db.bankPoolHistory( + params = HistoryParams( + start = 50L, + delta = -2, + poll_ms = 0 + ), bankAccountId = 1L // asking as Foo ) - assert(backward[0].expectRowId() <= 50 && backward.size == 2 && backward[0].dbRowId!! > backward[1].dbRowId!!) + assert(backward[0].row_id <= 50 && backward.size == 2 && backward[0].row_id > backward[1].row_id) } @Test fun cashoutTest() = setupDb { db ->