gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] branch master updated: allow timezones, use ISO time stamp fo


From: gnunet
Subject: [libeufin] branch master updated: allow timezones, use ISO time stamp for last fetch date
Date: Fri, 19 Jun 2020 14:25:43 +0200

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

dold pushed a commit to branch master
in repository libeufin.

The following commit(s) were added to refs/heads/master by this push:
     new be4ffcb  allow timezones, use ISO time stamp for last fetch date
be4ffcb is described below

commit be4ffcbcc55d656fbbf983de10d4e483949b127d
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Fri Jun 19 17:55:35 2020 +0530

    allow timezones, use ISO time stamp for last fetch date
---
 nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt    | 14 +++-
 .../tech/libeufin/nexus/bankaccount/BankAccount.kt |  9 ++-
 .../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt | 91 +++++++++++++++++-----
 .../main/kotlin/tech/libeufin/nexus/server/JSON.kt | 22 +++++-
 nexus/src/test/kotlin/authentication.kt            |  1 +
 util/src/main/kotlin/Ebics.kt                      | 14 +++-
 util/src/main/kotlin/time.kt                       |  4 +-
 7 files changed, 120 insertions(+), 35 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index abc7375..361186e 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -220,9 +220,14 @@ object NexusBankAccountsTable : IdTable<String>() {
     val bankCode = text("bankCode")
     val defaultBankConnection = reference("defaultBankConnection", 
NexusBankConnectionsTable).nullable()
 
-    val lastStatementCreationTimestamp = 
long("lastStatementCreationTimestamp").nullable()
-    val lastReportCreationTimestamp = 
long("lastReportCreationTimestamp").nullable()
-    val lastNotificationCreationTimestamp = 
long("lastNotificationCreationTimestamp").nullable()
+    // ISO-8601 zoned date time
+    val lastStatementCreationTimestamp = 
text("lastStatementCreationTimestamp").nullable()
+
+    // ISO-8601 zoned date time
+    val lastReportCreationTimestamp = 
text("lastReportCreationTimestamp").nullable()
+
+    // ISO-8601 zoned date time
+    val lastNotificationCreationTimestamp = 
text("lastNotificationCreationTimestamp").nullable()
 
     // Highest bank message ID that this bank account is aware of.
     val highestSeenBankMessageId = integer("highestSeenBankMessageId")
@@ -239,6 +244,9 @@ class NexusBankAccountEntity(id: EntityID<String>) : 
Entity<String>(id) {
     var defaultBankConnection by NexusBankConnectionEntity 
optionalReferencedOn NexusBankAccountsTable.defaultBankConnection
     var highestSeenBankMessageId by 
NexusBankAccountsTable.highestSeenBankMessageId
     var pain001Counter by NexusBankAccountsTable.pain001Counter
+    var lastStatementCreationTimestamp by 
NexusBankAccountsTable.lastStatementCreationTimestamp
+    var lastReportCreationTimestamp by 
NexusBankAccountsTable.lastReportCreationTimestamp
+    var lastNotificationCreationTimestamp by 
NexusBankAccountsTable.lastNotificationCreationTimestamp
 }
 
 object EbicsSubscribersTable : IntIdTable() {
diff --git 
a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
index 396a45f..76d2524 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -236,10 +236,10 @@ fun addPaymentInitiation(paymentData: Pain001Data, 
debitorAccount: NexusBankAcco
 suspend fun fetchBankAccountTransactions(
     client: HttpClient,
     fetchSpec: FetchSpecJson,
-    accountid: String
+    accountId: String
 ) {
     val res = transaction {
-        val acct = NexusBankAccountEntity.findById(accountid)
+        val acct = NexusBankAccountEntity.findById(accountId)
         if (acct == null) {
             throw NexusError(
                 HttpStatusCode.NotFound,
@@ -263,7 +263,8 @@ suspend fun fetchBankAccountTransactions(
             fetchEbicsBySpec(
                 fetchSpec,
                 client,
-                res.connectionName
+                res.connectionName,
+                accountId
             )
         }
         else -> throw NexusError(
@@ -271,6 +272,6 @@ suspend fun fetchBankAccountTransactions(
             "Connection type '${res.connectionType}' not implemented"
         )
     }
-    ingestBankMessagesIntoAccount(res.connectionName, accountid)
+    ingestBankMessagesIntoAccount(res.connectionName, accountId)
     ingestTalerTransactions()
 }
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
index 022aa64..9aa161f 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -51,8 +51,10 @@ import tech.libeufin.util.ebics_h004.HTDResponseOrderData
 import java.io.ByteArrayOutputStream
 import java.security.interfaces.RSAPrivateCrtKey
 import java.security.interfaces.RSAPublicKey
-import java.time.LocalDate
+import java.time.Instant
 import java.time.LocalDateTime
+import java.time.ZoneOffset
+import java.time.ZonedDateTime
 import java.time.format.DateTimeFormatter
 import java.util.*
 import javax.crypto.EncryptedPrivateKeyInfo
@@ -63,37 +65,88 @@ private data class EbicsFetchSpec(
     val orderParams: EbicsOrderParams
 )
 
-suspend fun fetchEbicsBySpec(fetchSpec: FetchSpecJson, client: HttpClient, 
bankConnectionId: String) {
+suspend fun fetchEbicsBySpec(
+    fetchSpec: FetchSpecJson,
+    client: HttpClient,
+    bankConnectionId: String,
+    accountId: String
+) {
     val subscriberDetails = transaction { 
getEbicsSubscriberDetails(bankConnectionId) }
+    val lastTimes = transaction {
+        val acct = NexusBankAccountEntity.findById(accountId)
+        if (acct == null) {
+            throw NexusError(
+                HttpStatusCode.NotFound,
+                "Account not found"
+            )
+        }
+        object {
+            val lastStatement = acct.lastStatementCreationTimestamp?.let {
+                ZonedDateTime.parse(it, DateTimeFormatter.ISO_DATE_TIME)
+            }
+            val lastReport = acct.lastReportCreationTimestamp?.let {
+                ZonedDateTime.parse(it, DateTimeFormatter.ISO_DATE_TIME)
+            }
+        }
+    }
     val specs = mutableListOf<EbicsFetchSpec>()
+
+    fun addForLevel(l: FetchLevel, p: EbicsOrderParams) {
+        when (fetchSpec.level) {
+            FetchLevel.ALL -> {
+                specs.add(EbicsFetchSpec("C52", p))
+                specs.add(EbicsFetchSpec("C53", p))
+            }
+            FetchLevel.REPORT -> {
+                specs.add(EbicsFetchSpec("C52", p))
+            }
+            FetchLevel.STATEMENT -> {
+                specs.add(EbicsFetchSpec("C53", p))
+            }
+        }
+    }
+
     when (fetchSpec) {
         is FetchSpecLatestJson -> {
             val p = EbicsStandardOrderParams()
-            when (fetchSpec.level) {
-                FetchLevel.ALL -> {
-                    specs.add(EbicsFetchSpec("C52", p))
-                    specs.add(EbicsFetchSpec("C53", p))
-                }
-                FetchLevel.REPORT -> {
-                    specs.add(EbicsFetchSpec("C52", p))
-                }
-                FetchLevel.STATEMENT -> {
-                    specs.add(EbicsFetchSpec("C53", p))
-                }
-            }
+            addForLevel(fetchSpec.level, p)
         }
         is FetchSpecAllJson -> {
-            val p = EbicsStandardOrderParams(EbicsDateRange(LocalDate.EPOCH, 
LocalDate.now()))
+            val p = EbicsStandardOrderParams(
+                EbicsDateRange(
+                    ZonedDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC),
+                    ZonedDateTime.now(ZoneOffset.UTC)
+                )
+            )
+            addForLevel(fetchSpec.level, p)
+        }
+        is FetchSpecSinceLastJson -> {
+            val pRep = EbicsStandardOrderParams(
+                EbicsDateRange(
+                    lastTimes.lastReport ?: ZonedDateTime.ofInstant(
+                        Instant.EPOCH,
+                        ZoneOffset.UTC
+                    ), ZonedDateTime.now(ZoneOffset.UTC)
+                )
+            )
+            val pStmt = EbicsStandardOrderParams(
+                EbicsDateRange(
+                    lastTimes.lastStatement ?: ZonedDateTime.ofInstant(
+                        Instant.EPOCH,
+                        ZoneOffset.UTC
+                    ), ZonedDateTime.now(ZoneOffset.UTC)
+                )
+            )
             when (fetchSpec.level) {
                 FetchLevel.ALL -> {
-                    specs.add(EbicsFetchSpec("C52", p))
-                    specs.add(EbicsFetchSpec("C53", p))
+                    specs.add(EbicsFetchSpec("C52", pRep))
+                    specs.add(EbicsFetchSpec("C53", pStmt))
                 }
                 FetchLevel.REPORT -> {
-                    specs.add(EbicsFetchSpec("C52", p))
+                    specs.add(EbicsFetchSpec("C52", pRep))
                 }
                 FetchLevel.STATEMENT -> {
-                    specs.add(EbicsFetchSpec("C53", p))
+                    specs.add(EbicsFetchSpec("C53", pStmt))
                 }
             }
         }
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
index 6a8dd8a..d7318ba 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/server/JSON.kt
@@ -26,7 +26,14 @@ import com.fasterxml.jackson.annotation.JsonValue
 import com.fasterxml.jackson.databind.JsonNode
 import tech.libeufin.nexus.BankTransaction
 import tech.libeufin.util.*
-import java.time.LocalDate
+import java.time.Instant
+import java.time.ZoneId
+import java.time.ZoneOffset
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeFormatterBuilder
+import java.time.temporal.ChronoField
+
 
 data class BackupRequestJson(
     val passphrase: String
@@ -62,6 +69,15 @@ class EbicsStandardOrderParamsEmptyJson : 
EbicsOrderParamsJson() {
     }
 }
 
+object EbicsDateFormat {
+    var fmt = DateTimeFormatterBuilder()
+        .append(DateTimeFormatter.ISO_DATE)
+        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
+        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
+        .parseDefaulting(ChronoField.OFFSET_SECONDS, 
ZoneId.systemDefault().rules.getOffset(Instant.now()).totalSeconds.toLong())
+        .toFormatter()
+}
+
 @JsonTypeName("standard-date-range")
 class EbicsStandardOrderParamsDateJson(
     val start: String,
@@ -70,8 +86,8 @@ class EbicsStandardOrderParamsDateJson(
     override fun toOrderParams(): EbicsOrderParams {
         val dateRange: EbicsDateRange? =
             EbicsDateRange(
-                LocalDate.parse(this.start),
-                LocalDate.parse(this.end)
+                ZonedDateTime.parse(this.start, EbicsDateFormat.fmt),
+                ZonedDateTime.parse(this.end, EbicsDateFormat.fmt)
             )
         return EbicsStandardOrderParams(dateRange)
     }
diff --git a/nexus/src/test/kotlin/authentication.kt 
b/nexus/src/test/kotlin/authentication.kt
index bcf3499..e0a0d75 100644
--- a/nexus/src/test/kotlin/authentication.kt
+++ b/nexus/src/test/kotlin/authentication.kt
@@ -2,6 +2,7 @@ package tech.libeufin.nexus
 
 import org.junit.Test
 import junit.framework.TestCase.assertEquals
+import tech.libeufin.nexus.server.extractUserAndPassword
 
 class AuthenticationTest {
     @Test
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
index 077a47d..1c7e167 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/util/src/main/kotlin/Ebics.kt
@@ -33,14 +33,15 @@ import java.math.BigInteger
 import java.security.SecureRandom
 import java.security.interfaces.RSAPrivateCrtKey
 import java.security.interfaces.RSAPublicKey
-import java.time.LocalDate
+import java.time.ZonedDateTime
 import java.util.*
 import java.util.zip.DeflaterInputStream
 import javax.xml.datatype.DatatypeFactory
+import javax.xml.datatype.XMLGregorianCalendar
 
 data class EbicsProtocolError(val statusCode: HttpStatusCode, val reason: 
String) : Exception(reason)
 
-data class EbicsDateRange(val start: LocalDate, val end: LocalDate)
+data class EbicsDateRange(val start: ZonedDateTime, val end: ZonedDateTime)
 
 sealed class EbicsOrderParams
 
@@ -86,6 +87,11 @@ private fun getNonce(size: Int): ByteArray {
     return ret
 }
 
+private fun getXmlDate(d: ZonedDateTime): XMLGregorianCalendar {
+    return DatatypeFactory.newInstance()
+        .newXMLGregorianCalendar(d.year, d.monthValue, d.dayOfMonth, 0, 0, 0, 
0, d.offset.totalSeconds / 60)
+}
+
 private fun makeOrderParams(orderParams: EbicsOrderParams): 
EbicsRequest.OrderParams {
     return when (orderParams) {
         is EbicsStandardOrderParams -> {
@@ -93,8 +99,8 @@ private fun makeOrderParams(orderParams: EbicsOrderParams): 
EbicsRequest.OrderPa
                 val r = orderParams.dateRange
                 if (r != null) {
                     this.dateRange = EbicsRequest.DateRange().apply {
-                        this.start = 
DatatypeFactory.newInstance().newXMLGregorianCalendar(r.start.toString())
-                        this.end = 
DatatypeFactory.newInstance().newXMLGregorianCalendar(r.end.toString())
+                        this.start = getXmlDate(r.start)
+                        this.end = getXmlDate(r.end)
                     }
                 }
             }
diff --git a/util/src/main/kotlin/time.kt b/util/src/main/kotlin/time.kt
index 6d6e378..4bd2f55 100644
--- a/util/src/main/kotlin/time.kt
+++ b/util/src/main/kotlin/time.kt
@@ -27,11 +27,11 @@ fun LocalDateTime.toZonedString(): String {
 }
 
 fun LocalDateTime.toDashedDate(): String {
-    return DateTimeFormatter.ISO_DATE.format(this)
+    return DateTimeFormatter.ISO_OFFSET_DATE.format(this)
 }
 
 fun parseDashedDate(date: String): LocalDateTime {
-    val dtf = DateTimeFormatter.ISO_DATE
+    val dtf = DateTimeFormatter.ISO_OFFSET_DATE
     val asDate = LocalDate.parse(date, dtf)
     return asDate.atStartOfDay()
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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