libeufin

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

commit bb01cf635a1bc206a4ffb583f550cd336a9f2500
parent d13b09a8a905387eb2013eb42f3fa68a2664f13c
Author: ms <ms@taler.net>
Date:   Tue, 19 Oct 2021 10:18:31 +0200

Access API.

Implement read operation on the 'account' resource.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt | 3++-
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 25+++++++++++++++++++++++--
Mutil/src/main/kotlin/HTTP.kt | 12++++++++++++
3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt @@ -115,6 +115,7 @@ object DemobankCustomersTable : LongIdTable() { val balance = text("balance") val username = text("username") val passwordHash = text("passwordHash") + val isDebit = bool("isDebit").default(false) } class DemobankCustomerEntity(id: EntityID<Long>) : LongEntity(id) { @@ -124,9 +125,9 @@ class DemobankCustomerEntity(id: EntityID<Long>) : LongEntity(id) { var balance by DemobankCustomersTable.balance var username by DemobankCustomersTable.username var passwordHash by DemobankCustomersTable.passwordHash + var isDebit by DemobankCustomersTable.isDebit } - /** * This table stores RSA public keys of subscribers. */ diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -1073,8 +1073,29 @@ val sandboxApp: Application.() -> Unit = { route("/access-api") { get("/accounts/{account_name}") { - // Authenticated. Accesses basic information (balance) - // about an account. (see docs) + val username = call.request.basicAuth() + val accountAccessed = call.getUriComponent("account_name") + if (username != accountAccessed) { + throw forbidden("Account '$accountAccessed' not allowed for '$username'") + } + val customer = transaction { + val res = DemobankCustomerEntity.find { + DemobankCustomersTable.username eq username + }.firstOrNull() + res + } ?: throw internalServerError("Account '$accountAccessed' not found AFTER authentication!") + val creditDebitIndicator = if (customer.isDebit) { + "debit" + } else { + "credit" + } + call.respond(object { + val balance = { + val amount = customer.balance + val credit_debit_indicator = creditDebitIndicator + } + }) + return@get } get("/accounts/{account_name}/history") { diff --git a/util/src/main/kotlin/HTTP.kt b/util/src/main/kotlin/HTTP.kt @@ -41,6 +41,14 @@ fun extractToken(authHeader: String): String { return "${tokenSplit[0]}:${URLDecoder.decode(tokenSplit[1], Charsets.UTF_8)}" } +fun forbidden(msg: String): UtilError { + return UtilError( + HttpStatusCode.Forbidden, + msg, + ec = LibeufinErrorCode.LIBEUFIN_EC_NONE + ) +} + fun internalServerError( reason: String, libeufinErrorCode: LibeufinErrorCode? = LibeufinErrorCode.LIBEUFIN_EC_NONE @@ -106,6 +114,10 @@ fun ApplicationCall.getUriComponent(name: String): String { * - null if the authentication is disabled (during tests, for example) * - the name of the authenticated user * - throw exception when the authentication fails + * + * Note: at this point it is ONLY checked whether the user provided + * a valid password for the username mentioned in the Authorization header. + * The actual access to the resources must be later checked by each handler. */ fun ApplicationRequest.basicAuth(): String? { val withAuth = this.call.ensureAttribute(WITH_AUTH_ATTRIBUTE_KEY)