commit 5c671b88781678b01937a3893438c97d6f2fd5dd
parent 5086e2514bc6f0881b630b20d07ce0737bc9fbea
Author: Antoine A <>
Date: Tue, 17 Oct 2023 12:52:28 +0000
Cleanup
Diffstat:
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 ->