commit f07a65e633b2961ef5f0447f086d85e1ec7f8f7d
parent dc723836229868294ea3bfdcaa76550e662bda23
Author: MS <ms@taler.net>
Date: Mon, 29 Jun 2020 15:08:47 +0200
implement composite primary keys
Diffstat:
4 files changed, 38 insertions(+), 46 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -210,32 +210,15 @@ class PaymentInitiationEntity(id: EntityID<Long>) : LongEntity(id) {
* This table contains the bank accounts that are offered by the bank.
* The bank account label (as assigned by the bank) is the primary key.
*/
-object OfferedBankAccountsTable : IdTable<String>() {
- override val id = text("id").entityId()
+object OfferedBankAccountsTable : Table() {
+ val offeredAccountId = text("id")
val bankConnection = reference("bankConnection", NexusBankConnectionsTable)
val iban = text("iban")
val bankCode = text("bankCode")
val accountHolder = text("holderName")
val imported = reference("imported", NexusBankAccountsTable).nullable()
-}
-
-class OfferedBankAccountEntity(id: EntityID<String>) : Entity<String>(id) {
- companion object : EntityClass<String, OfferedBankAccountEntity>(OfferedBankAccountsTable)
- var bankConnection by NexusBankConnectionEntity referencedOn OfferedBankAccountsTable.bankConnection
- var iban by OfferedBankAccountsTable.iban
- var bankCode by OfferedBankAccountsTable.bankCode
- var accountHolder by OfferedBankAccountsTable.accountHolder
- var imported by NexusBankAccountEntity optionalReferencedOn OfferedBankAccountsTable.imported
-}
-object AvailableConnectionsForAccountsTable : IntIdTable() {
- val bankAccount = reference("bankAccount", NexusBankAccountsTable)
- val bankConnection = reference("bankConnection", NexusBankConnectionsTable)
-}
-class AvailableConnectionForAccountEntity(id: EntityID<Int>) : IntEntity(id) {
- companion object : IntEntityClass<AvailableConnectionForAccountEntity>(AvailableConnectionsForAccountsTable)
- var bankAccount by NexusBankAccountEntity referencedOn AvailableConnectionsForAccountsTable.bankAccount
- var bankConnection by NexusBankConnectionEntity referencedOn AvailableConnectionsForAccountsTable.bankConnection
+ override val primaryKey = PrimaryKey(offeredAccountId, bankConnection)
}
/**
@@ -415,8 +398,7 @@ fun dbCreateTables(dbName: String) {
FacadesTable,
TalerFacadeStateTable,
NexusScheduledTasksTable,
- OfferedBankAccountsTable,
- AvailableConnectionsForAccountsTable
+ OfferedBankAccountsTable
)
}
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -26,9 +26,11 @@ import io.ktor.client.HttpClient
import io.ktor.http.HttpStatusCode
import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.w3c.dom.Document
import tech.libeufin.nexus.*
+import tech.libeufin.nexus.OfferedBankAccountsTable.iban
import tech.libeufin.nexus.ebics.fetchEbicsBySpec
import tech.libeufin.nexus.ebics.submitEbicsPaymentInitiation
import tech.libeufin.nexus.server.FetchSpecJson
@@ -305,16 +307,20 @@ suspend fun fetchBankAccountTransactions(
fun importBankAccount(call: ApplicationCall, offeredBankAccountId: String, nexusBankAccountId: String) {
transaction {
val conn = requireBankConnection(call, "connid")
- val offeredAccount = OfferedBankAccountEntity.findById(offeredBankAccountId) ?: throw NexusError(
- HttpStatusCode.NotFound, "Could not found raw bank account '${offeredBankAccountId}'"
+ // first get handle of the offered bank account
+ val offeredAccount = OfferedBankAccountsTable.select {
+ OfferedBankAccountsTable.offeredAccountId eq offeredBankAccountId
+ }.firstOrNull() ?: throw NexusError(
+ HttpStatusCode.NotFound, "Could not find raw bank account '${offeredBankAccountId}'"
)
// detect name collisions first.
NexusBankAccountEntity.findById(nexusBankAccountId).run {
val importedAccount = when(this) {
is NexusBankAccountEntity -> {
- if (this.iban != offeredAccount.iban) {
+ if (this.iban != offeredAccount[OfferedBankAccountsTable.iban]) {
throw NexusError(
HttpStatusCode.Conflict,
+ // different accounts == different IBANs
"Cannot import two different accounts under one label: ${nexusBankAccountId}"
)
}
@@ -322,20 +328,16 @@ fun importBankAccount(call: ApplicationCall, offeredBankAccountId: String, nexus
}
else -> {
val newImportedAccount = NexusBankAccountEntity.new(nexusBankAccountId) {
- iban = offeredAccount.iban
- bankCode = offeredAccount.bankCode
+ iban = offeredAccount[OfferedBankAccountsTable.iban]
+ bankCode = offeredAccount[OfferedBankAccountsTable.bankCode]
defaultBankConnection = conn
highestSeenBankMessageId = 0
- accountHolder = offeredAccount.accountHolder
+ accountHolder = offeredAccount[OfferedBankAccountsTable.accountHolder]
}
- offeredAccount.imported = newImportedAccount
+ offeredAccount[OfferedBankAccountsTable.imported] = newImportedAccount
newImportedAccount
}
}
- AvailableConnectionForAccountEntity.new {
- bankAccount = importedAccount
- bankConnection = conn
- }
}
}
}
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -43,6 +43,7 @@ import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.post
import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.not
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
import org.jetbrains.exposed.sql.transactions.transaction
@@ -344,19 +345,19 @@ suspend fun ebicsFetchAccounts(connId: String, client: HttpClient) {
response.orderData.toString(Charsets.UTF_8)
)
transaction {
- payload.value.partnerInfo.accountInfoList?.forEach {
- OfferedBankAccountEntity.new(id = it.id) {
- accountHolder = it.accountHolder ?: "NOT-GIVEN"
- iban = it.accountNumberList?.filterIsInstance<EbicsTypes.GeneralAccountNumber>()
+ payload.value.partnerInfo.accountInfoList?.forEach { accountInfo ->
+ OfferedBankAccountsTable.insert { newRow ->
+ newRow[accountHolder] = accountInfo.accountHolder ?: "NOT GIVEN"
+ newRow[iban] = accountInfo.accountNumberList?.filterIsInstance<EbicsTypes.GeneralAccountNumber>()
?.find { it.international }?.value
?: throw NexusError(HttpStatusCode.NotFound, reason = "bank gave no IBAN")
- bankCode = it.bankCodeList?.filterIsInstance<EbicsTypes.GeneralBankCode>()
+ newRow[bankCode] = accountInfo.bankCodeList?.filterIsInstance<EbicsTypes.GeneralBankCode>()
?.find { it.international }?.value
?: throw NexusError(
HttpStatusCode.NotFound,
reason = "bank gave no BIC"
)
- bankConnection = requireBankConnectionInternal(connId)
+ newRow[bankConnection] = requireBankConnectionInternal(connId).id
}
}
}
@@ -373,6 +374,7 @@ fun Route.ebicsBankProtocolRoutes(client: HttpClient) {
}
}
+
fun Route.ebicsBankConnectionRoutes(client: HttpClient) {
post("/send-ini") {
val subscriber = transaction {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/server/NexusServer.kt
@@ -49,9 +49,15 @@ import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.toByteReadChannel
import io.ktor.utils.io.jvm.javaio.toInputStream
import org.jetbrains.exposed.sql.and
+import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.event.Level
import tech.libeufin.nexus.*
+import tech.libeufin.nexus.OfferedBankAccountsTable.accountHolder
+import tech.libeufin.nexus.OfferedBankAccountsTable.bankCode
+import tech.libeufin.nexus.OfferedBankAccountsTable.iban
+import tech.libeufin.nexus.OfferedBankAccountsTable.imported
+import tech.libeufin.nexus.OfferedBankAccountsTable.offeredAccountId
import tech.libeufin.nexus.bankaccount.*
import tech.libeufin.nexus.ebics.*
import tech.libeufin.util.*
@@ -788,16 +794,16 @@ fun serverMain(dbName: String, host: String) {
val ret = mutableListOf<OfferedBankAccount>()
transaction {
val conn = requireBankConnection(call, "connid")
- OfferedBankAccountEntity.find {
+ OfferedBankAccountsTable.select {
OfferedBankAccountsTable.bankConnection eq conn.id.value
- }.forEach {
+ }.forEach {resultRow ->
ret.add(
OfferedBankAccount(
- ownerName = it.accountHolder,
- iban = it.iban,
- bic = it.bankCode,
- offeredAccountId = it.id.value,
- nexusBankAccountId = it.imported?.id?.value
+ ownerName = resultRow[accountHolder],
+ iban = resultRow[iban],
+ bic = resultRow[bankCode],
+ offeredAccountId = resultRow[offeredAccountId],
+ nexusBankAccountId = resultRow[imported]?.value // is 'value' the id?
)
)
}