gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated: Ordering code.


From: gnunet
Subject: [libeufin] branch master updated: Ordering code.
Date: Wed, 08 Apr 2020 18:29:03 +0200

This is an automated email from the git hooks/post-receive script.

marcello pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new 433c441  Ordering code.
433c441 is described below

commit 433c4415be8a025dfe558a9afa003703309ad9c8
Author: Marcello Stanisci <address@hidden>
AuthorDate: Wed Apr 8 18:28:53 2020 +0200

    Ordering code.
---
 .../src/main/kotlin/tech/libeufin/nexus/Helpers.kt |  45 +++-
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  |   6 +
 nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt | 281 ++++++---------------
 3 files changed, 134 insertions(+), 198 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 555c060..e5b38bf 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -2,6 +2,11 @@ package tech.libeufin.nexus
 
 import io.ktor.application.ApplicationCall
 import io.ktor.http.HttpStatusCode
+import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.transactions.transaction
+import tech.libeufin.util.CryptoUtil
+import tech.libeufin.util.base64ToBytes
+import javax.sql.rowset.serial.SerialBlob
 
 /**
  * Inserts spaces every 2 characters, and a newline after 8 pairs.
@@ -71,4 +76,42 @@ fun expectAcctidTransaction(param: String?): 
EbicsAccountInfoEntity {
         throw NexusError(HttpStatusCode.BadRequest, "Null Acctid given")
     }
     return EbicsAccountInfoEntity.findById(param) ?: throw 
NexusError(HttpStatusCode.NotFound, "Account: $param not found")
-}
\ No newline at end of file
+}
+
+/**
+ * This helper function parses a Authorization:-header line, decode the 
credentials
+ * and returns a pair made of username and hashed (sha256) password.  The 
hashed value
+ * will then be compared with the one kept into the database.
+ */
+fun extractUserAndHashedPassword(authorizationHeader: String): Pair<String, 
ByteArray> {
+    val (username, password) = try {
+        val split = authorizationHeader.split(" ")
+        val valueUtf8 = String(base64ToBytes(split[1]), Charsets.UTF_8) // 
newline introduced here: BUG!
+        valueUtf8.split(":")
+    } catch (e: java.lang.Exception) {
+        throw NexusError(
+            HttpStatusCode.BadRequest, "invalid Authorization:-header received"
+        )
+    }
+    return Pair(username, CryptoUtil.hashStringSHA256(password))
+}
+
+/**
+ * Test HTTP basic auth.  Throws error if password is wrong
+ *
+ * @param authorization the Authorization:-header line.
+ * @return subscriber id
+ */
+fun authenticateRequest(authorization: String?): String {
+    val headerLine = authorization ?: throw NexusError(
+        HttpStatusCode.BadRequest, "Authentication:-header line not found"
+    )
+    logger.debug("Checking for authorization: $headerLine")
+    val subscriber = transaction {
+        val (user, pass) = extractUserAndHashedPassword(headerLine)
+        EbicsSubscriberEntity.find {
+            EbicsSubscribersTable.id eq user and 
(EbicsSubscribersTable.password eq SerialBlob(pass))
+        }.firstOrNull()
+    } ?: throw NexusError(HttpStatusCode.Forbidden, "Wrong password")
+    return subscriber.id.value
+}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index ec3fe96..ae80bef 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -388,6 +388,12 @@ fun main() {
                 return@get
             }
 
+            get("/taler/test-auth") {
+                authenticateRequest(call.request.headers["Authorization"])
+                call.respondText("Authenticated!", ContentType.Text.Plain, 
HttpStatusCode.OK)
+                return@get
+            }
+
             post("/ebics/subscribers/{id}/sendPTK") {
                 val id = expectId(call.parameters["id"])
                 val paramsJson = call.receive<EbicsStandardOrderParamsJson>()
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index a209262..bc18142 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -8,59 +8,17 @@ import io.ktor.response.respondText
 import io.ktor.routing.Route
 import io.ktor.routing.get
 import io.ktor.routing.post
-import io.ktor.routing.route
 import org.jetbrains.exposed.dao.Entity
-import org.jetbrains.exposed.dao.EntityID
-import org.jetbrains.exposed.dao.LongEntity
 import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.SqlExpressionBuilder.lessEq
 import org.jetbrains.exposed.sql.transactions.transaction
 import org.joda.time.DateTime
 import org.joda.time.format.DateTimeFormat
-import org.joda.time.format.DateTimeFormatter
 import tech.libeufin.util.CryptoUtil
-import tech.libeufin.util.base64ToBytes
-import java.lang.Exception
-import javax.sql.rowset.serial.SerialBlob
 import kotlin.math.abs
 
-/**
- * This helper function parses a Authorization:-header line, decode the 
credentials
- * and returns a pair made of username and hashed (sha256) password.  The 
hashed value
- * will then be compared with the one kept into the database.
- */
-fun extractUserAndHashedPassword(authorizationHeader: String): Pair<String, 
ByteArray> {
-    val (username, password) = try {
-        val split = authorizationHeader.split(" ")
-        val valueUtf8 = String(base64ToBytes(split[1]), Charsets.UTF_8) // 
newline introduced here: BUG!
-        valueUtf8.split(":")
-    } catch (e: Exception) {
-        throw NexusError(
-            HttpStatusCode.BadRequest, "invalid Authorization:-header received"
-        )
-    }
-    return Pair(username, CryptoUtil.hashStringSHA256(password))
-}
-
 class Taler(app: Route) {
 
-    init {
-        /** transform raw CAMT.053 payment records to more Taler-friendly
-         * database rows. */
-        digest(app)
-
-        /** process the incoming payments, and craft refund payments (although
-         * do not execute them) for those incoming payments that had a wrong
-         * (!= public key) subject. */
-        refund(app)
-
-        /** Tester for HTTP basic auth. */
-        testAuth(app)
-    }
-
-    /**
-     * Payment initiating data structures: one endpoint "$BASE_URL/transfer".
-     */
+    /** Payment initiating data structures: one endpoint "$BASE_URL/transfer". 
*/
     private data class TalerTransferRequest(
         val request_uid: String,
         val amount: String,
@@ -68,20 +26,13 @@ class Taler(app: Route) {
         val wtid: String,
         val credit_account: String
     )
-
     private data class TalerTransferResponse(
         // point in time when the nexus put the payment instruction into the 
database.
         val timestamp: Long,
         val row_id: Long
     )
 
-    /**
-     * History accounting data structures
-     */
-
-    /**
-     * Incoming payments.
-     */
+    /** History accounting data structures */
     private data class TalerIncomingBankTransaction(
         val row_id: Long,
         val date: Long, // timestamp
@@ -90,14 +41,9 @@ class Taler(app: Route) {
         val debit_account: String,
         val reserve_pub: String
     )
-
     private data class TalerIncomingHistory(
         var incoming_transactions: MutableList<TalerIncomingBankTransaction> = 
mutableListOf()
     )
-
-    /**
-     * Outgoing payments.
-     */
     private data class TalerOutgoingBankTransaction(
         val row_id: Long,
         val date: Long, // timestamp
@@ -107,13 +53,11 @@ class Taler(app: Route) {
         val wtid: String,
         val exchange_base_url: String
     )
-
     private data class TalerOutgoingHistory(
         var outgoing_transactions: MutableList<TalerOutgoingBankTransaction> = 
mutableListOf()
     )
-    /**
-     * Test APIs' data structures.
-     */
+
+    /** Test APIs' data structures. */
     private data class TalerAdminAddIncoming(
         val amount: String,
         val reserve_pub: String,
@@ -125,6 +69,8 @@ class Taler(app: Route) {
         val row_id: Long
     )
 
+    /** Helper functions */
+
     private fun <T : Entity<Long>> SizedIterable<T>.orderTaler(delta: Int): 
List<T> {
         return if (delta < 0) {
             this.sortedByDescending { it.id }
@@ -132,35 +78,12 @@ class Taler(app: Route) {
             this.sortedBy { it.id }
         }
     }
-
-    /**
-     * Test HTTP basic auth.  Throws error if password is wrong
-     *
-     * @param authorization the Authorization:-header line.
-     * @return subscriber id
-     */
-    private fun authenticateRequest(authorization: String?): String {
-        val headerLine = authorization ?: throw NexusError(
-            HttpStatusCode.BadRequest, "Authentication:-header line not found"
-        )
-        logger.debug("Checking for authorization: $headerLine")
-        val subscriber = transaction {
-            val (user, pass) = extractUserAndHashedPassword(headerLine)
-            EbicsSubscriberEntity.find {
-                EbicsSubscribersTable.id eq user and 
(EbicsSubscribersTable.password eq SerialBlob(pass))
-            }.firstOrNull()
-        } ?: throw NexusError(HttpStatusCode.Forbidden, "Wrong password")
-        return subscriber.id.value
-    }
-
     private fun getPaytoUri(name: String, iban: String, bic: String): String {
         return "payto://$iban/$bic?receiver-name=$name"
     }
-
     private fun parseDate(date: String): DateTime {
         return DateTime.parse(date, DateTimeFormat.forPattern("YYYY-MM-DD"))
     }
-
     /**
      * Builds the comparison operator for history entries based on the
      * sign of 'delta'
@@ -176,7 +99,6 @@ class Taler(app: Route) {
             }
         }
     }
-
     /**
      * Helper handling 'start' being optional and its dependence on 'delta'.
      */
@@ -198,107 +120,40 @@ class Taler(app: Route) {
         }
     }
 
-    /**
-     * Implement the Taler wire API transfer method.
-     */
-    private fun transfer(app: Route) {
+    /** attaches Taler endpoints to the main Web server */
+    init {
         app.post("/taler/transfer") {
             call.respond(HttpStatusCode.OK, NexusErrorJson("Not implemented"))
             return@post
         }
-    }
-
-
-    /**
-     * Respond with ONLY the good transfer made to the exchange.
-     * A 'good' transfer is one whose subject line is a plausible
-     * EdDSA public key encoded in Crockford base32.
-     */
-    private fun historyIncoming(app: Route) {
-        app.get("/taler/history/incoming") {
-            val subscriberId = 
authenticateRequest(call.request.headers["Authorization"])
-            val delta: Int = expectInt(call.expectUrlParameter("delta"))
-            val start: Long = 
handleStartArgument(call.request.queryParameters["start"], delta)
-            val history = TalerIncomingHistory()
-            val startCmpOp = getComparisonOperator(delta, start)
+        
app.post("/ebics/taler/{id}/accounts/{acctid}/refund-invalid-payments") {
             transaction {
-                val subscriberBankAccount = 
getBankAccountsInfoFromId(subscriberId)
-                TalerIncomingPaymentEntry.find {
-                    TalerIncomingPayments.valid eq true and startCmpOp
-                }.orderTaler(delta).subList(0, abs(delta)).forEach {
-                    history.incoming_transactions.add(
-                        TalerIncomingBankTransaction(
-                            date = parseDate(it.payment.bookingDate).millis / 
1000, // timestamp in seconds
-                            row_id = it.id.value,
-                            amount = 
"${it.payment.currency}:${it.payment.amount}",
-                            reserve_pub = 
it.payment.unstructuredRemittanceInformation,
-                            debit_account = getPaytoUri(
-                                it.payment.debitorName, 
it.payment.debitorIban, it.payment.counterpartBic
-                            ),
-                            credit_account = getPaytoUri(
-                                it.payment.creditorName, 
it.payment.creditorIban, subscriberBankAccount.first().bankCode
-                            )
-                        )
+                val subscriber = expectIdTransaction(call.parameters["id"])
+                val acctid = expectAcctidTransaction(call.parameters["acctid"])
+                if (acctid.subscriber.id != subscriber.id) {
+                    throw NexusError(
+                        HttpStatusCode.Forbidden,
+                        "Such subscriber (${subscriber.id}) can't drive such 
account (${acctid.id})"
                     )
                 }
-            }
-            call.respond(history)
-            return@get
-        }
-    }
-
-    /**
-     * Respond with all the transfers that the exchange made to merchants.
-     * It can include also those transfers made to reimburse some invalid
-     * incoming payment.
-     */
-    private fun historyOutgoing(app: Route) {
-        app.get("/taler/history/outgoing") {
-
-            /* sanitize URL arguments */
-            val subscriberId = 
authenticateRequest(call.request.headers["Authorization"])
-            val delta: Int = expectInt(call.expectUrlParameter("delta"))
-            val start: Long = 
handleStartArgument(call.request.queryParameters["start"], delta)
-            val startCmpOp = getComparisonOperator(delta, start)
-
-            /* retrieve database elements */
-            val history = TalerOutgoingHistory()
-            transaction {
-                /** Retrieve all the outgoing payments from the _raw 
transactions table_ */
-                val subscriberBankAccount = 
getBankAccountsInfoFromId(subscriberId)
-                EbicsRawBankTransactionEntry.find {
-                    EbicsRawBankTransactionsTable.debitorIban eq 
subscriberBankAccount.first().iban and startCmpOp
-                }.orderTaler(delta).subList(0, abs(delta)).forEach {
-                    history.outgoing_transactions.add(
-                        TalerOutgoingBankTransaction(
-                            row_id = it.id.value,
-                            amount = "${it.currency}:${it.amount}",
-                            wtid = it.unstructuredRemittanceInformation,
-                            date = parseDate(it.bookingDate).millis / 1000,
-                            credit_account = it.creditorIban,
-                            debit_account = it.debitorIban,
-                            exchange_base_url = 
"FIXME-to-request-along-subscriber-registration"
-                        )
+                TalerIncomingPaymentEntry.find {
+                    TalerIncomingPayments.processed eq false and 
(TalerIncomingPayments.valid eq false)
+                }.forEach {
+                    createPain001entry(
+                        Pain001Data(
+                            creditorName = it.payment.debitorName,
+                            creditorIban = it.payment.debitorIban,
+                            creditorBic = it.payment.counterpartBic,
+                            sum = calculateRefund(it.payment.amount),
+                            subject = "Taler refund"
+                        ),
+                        acctid.id.value
                     )
+                    it.processed = true
                 }
             }
-            call.respond(
-                HttpStatusCode.OK,
-                history
-            )
-            return@get
-        }
-    }
-
-    private fun testAuth(app: Route) {
-        app.get("/taler/test-auth") {
-            authenticateRequest(call.request.headers["Authorization"])
-            call.respondText("Authenticated!", ContentType.Text.Plain, 
HttpStatusCode.OK)
-            return@get
+            return@post
         }
-    }
-
-    private fun digest(app: Route) {
         app.post("/ebics/taler/{id}/digest-incoming-transactions") {
             val id = expectId(call.parameters["id"])
             // first find highest ID value of already processed rows.
@@ -341,36 +196,68 @@ class Taler(app: Route) {
             )
             return@post
         }
-    }
-
-    private fun refund(app: Route) {
-        
app.post("/ebics/taler/{id}/accounts/{acctid}/refund-invalid-payments") {
+        app.get("/taler/history/outgoing") {
+            /* sanitize URL arguments */
+            val subscriberId = 
authenticateRequest(call.request.headers["Authorization"])
+            val delta: Int = expectInt(call.expectUrlParameter("delta"))
+            val start: Long = 
handleStartArgument(call.request.queryParameters["start"], delta)
+            val startCmpOp = getComparisonOperator(delta, start)
+            /* retrieve database elements */
+            val history = TalerOutgoingHistory()
             transaction {
-                val subscriber = expectIdTransaction(call.parameters["id"])
-                val acctid = expectAcctidTransaction(call.parameters["acctid"])
-                if (acctid.subscriber.id != subscriber.id) {
-                    throw NexusError(
-                        HttpStatusCode.Forbidden,
-                        "Such subscriber (${subscriber.id}) can't drive such 
account (${acctid.id})"
+                /** Retrieve all the outgoing payments from the _raw 
transactions table_ */
+                val subscriberBankAccount = 
getBankAccountsInfoFromId(subscriberId)
+                EbicsRawBankTransactionEntry.find {
+                    EbicsRawBankTransactionsTable.debitorIban eq 
subscriberBankAccount.first().iban and startCmpOp
+                }.orderTaler(delta).subList(0, abs(delta)).forEach {
+                    history.outgoing_transactions.add(
+                        TalerOutgoingBankTransaction(
+                            row_id = it.id.value,
+                            amount = "${it.currency}:${it.amount}",
+                            wtid = it.unstructuredRemittanceInformation,
+                            date = parseDate(it.bookingDate).millis / 1000,
+                            credit_account = it.creditorIban,
+                            debit_account = it.debitorIban,
+                            exchange_base_url = 
"FIXME-to-request-along-subscriber-registration"
+                        )
                     )
                 }
+            }
+            call.respond(
+                HttpStatusCode.OK,
+                history
+            )
+            return@get
+        }
+        app.get("/taler/history/incoming") {
+            val subscriberId = 
authenticateRequest(call.request.headers["Authorization"])
+            val delta: Int = expectInt(call.expectUrlParameter("delta"))
+            val start: Long = 
handleStartArgument(call.request.queryParameters["start"], delta)
+            val history = TalerIncomingHistory()
+            val startCmpOp = getComparisonOperator(delta, start)
+            transaction {
+                val subscriberBankAccount = 
getBankAccountsInfoFromId(subscriberId)
                 TalerIncomingPaymentEntry.find {
-                    TalerIncomingPayments.processed eq false and 
(TalerIncomingPayments.valid eq false)
-                }.forEach {
-                    createPain001entry(
-                        Pain001Data(
-                            creditorName = it.payment.debitorName,
-                            creditorIban = it.payment.debitorIban,
-                            creditorBic = it.payment.counterpartBic,
-                            sum = calculateRefund(it.payment.amount),
-                            subject = "Taler refund"
-                        ),
-                        acctid.id.value
+                    TalerIncomingPayments.valid eq true and startCmpOp
+                }.orderTaler(delta).subList(0, abs(delta)).forEach {
+                    history.incoming_transactions.add(
+                        TalerIncomingBankTransaction(
+                            date = parseDate(it.payment.bookingDate).millis / 
1000, // timestamp in seconds
+                            row_id = it.id.value,
+                            amount = 
"${it.payment.currency}:${it.payment.amount}",
+                            reserve_pub = 
it.payment.unstructuredRemittanceInformation,
+                            debit_account = getPaytoUri(
+                                it.payment.debitorName, 
it.payment.debitorIban, it.payment.counterpartBic
+                            ),
+                            credit_account = getPaytoUri(
+                                it.payment.creditorName, 
it.payment.creditorIban, subscriberBankAccount.first().bankCode
+                            )
+                        )
                     )
-                    it.processed = true
                 }
             }
-            return@post
+            call.respond(history)
+            return@get
         }
     }
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]