gnunet-svn
[Top][All Lists]
Advanced

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

[libeufin] 02/02: Overloading POST ../bank-transport.


From: gnunet
Subject: [libeufin] 02/02: Overloading POST ../bank-transport.
Date: Thu, 14 May 2020 17:49:55 +0200

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

ms pushed a commit to branch master
in repository libeufin.

commit 8f118987a6fe292e1fd5a7d16fe0baf63a5f3240
Author: MS <address@hidden>
AuthorDate: Thu May 14 17:47:23 2020 +0200

    Overloading POST ../bank-transport.
    
    Plus getting the Taler facade to compile again.
---
 nexus/build.gradle                                 |   2 +-
 .../src/main/kotlin/tech/libeufin/nexus/Helpers.kt |  21 ++-
 nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt  |  10 +-
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  | 159 +++++++++++----------
 nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt |  86 +++++------
 nexus/src/test/kotlin/PainGeneration.kt            |   2 -
 nexus/src/test/kotlin/taler.kt                     |  10 +-
 util/src/main/kotlin/ParametersChecks.kt           |   7 +
 8 files changed, 167 insertions(+), 130 deletions(-)

diff --git a/nexus/build.gradle b/nexus/build.gradle
index b2a264a..ff58a78 100644
--- a/nexus/build.gradle
+++ b/nexus/build.gradle
@@ -16,7 +16,7 @@ plugins {
 
 sourceSets {
     main.kotlin.srcDirs = ["src/main/kotlin"]
-    main.kotlin.excludes = ["**/MainDeprecated.kt", "**/taler.kt"]
+    main.kotlin.excludes = ["**/MainDeprecated.kt"]
 }
 
 task installToPrefix(type: Copy) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 93e5eb9..135d53b 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -1,5 +1,7 @@
 package tech.libeufin.nexus
 
+import com.google.gson.Gson
+import com.google.gson.JsonObject
 import io.ktor.client.HttpClient
 import io.ktor.http.HttpStatusCode
 import org.jetbrains.exposed.sql.and
@@ -60,6 +62,12 @@ fun extractFirstBic(bankCodes: 
List<EbicsTypes.AbstractBankCode>?): String? {
     return null
 }
 
+fun getTransportFromJsonObject(jo: JsonObject): Transport {
+    return Gson().fromJson(
+        expectNonNull(jo.get("transport")).asJsonObject, Transport::class.java
+    )
+}
+
 /**
  * Retrieve bank account details, only if user owns it.
  */
@@ -128,7 +136,7 @@ fun getEbicsSubscriberDetailsInternal(subscriber: 
EbicsSubscriberEntity): EbicsC
     )
 }
 
-fun getEbicsTransport(userId: String, transportId: String?): 
EbicsSubscriberEntity {
+fun getEbicsTransport(userId: String, transportId: String? = null): 
EbicsSubscriberEntity {
     val transport = transaction {
         if (transportId == null) {
             return@transaction EbicsSubscriberEntity.all().first()
@@ -150,7 +158,7 @@ fun getEbicsTransport(userId: String, transportId: 
String?): EbicsSubscriberEnti
 
 /**
  * Retrieve Ebics subscriber details given a Transport
- * object and handling the default case.
+ * object and handling the default case (when this latter is null).
  */
 fun getEbicsSubscriberDetails(userId: String, transportId: String?): 
EbicsClientSubscriberDetails {
     val transport = getEbicsTransport(userId, transportId)
@@ -370,6 +378,15 @@ fun getPreparedPayment(uuid: String): 
PreparedPaymentEntity {
     )
 }
 
+fun getNexusUser(id: String): NexusUserEntity {
+    return transaction {
+        NexusUserEntity.findById(id)
+    } ?: throw NexusError(
+        HttpStatusCode.NotFound,
+        "User '$id' not found"
+    )
+}
+
 /**
  * Insert one row in the database, and leaves it marked as non-submitted.
  * @param debtorAccountId the mnemonic id assigned by the bank to one bank
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
index 2a8f72d..8f27ec9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt
@@ -1,8 +1,6 @@
 package tech.libeufin.nexus
 
-import com.sun.jdi.connect.Transport
 import tech.libeufin.util.*
-import java.lang.NullPointerException
 import java.time.LocalDate
 
 data class EbicsBackupRequestJson(
@@ -79,10 +77,10 @@ data class RawPayments(
 /*************************************************
  *  API types (used as requests/responses types) *
  *************************************************/
-data class BankTransport<T, S>(
-    val transport: tech.libeufin.nexus.Transport,
-    val backup: T?,
-    val data: S?
+data class BankTransport(
+    val transport: Transport,
+    val backup: Any? = null,
+    val data: Any?
 )
 
 /**
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 488dce7..43db3b2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -19,6 +19,8 @@
 
 package tech.libeufin.nexus
 
+import com.google.gson.Gson
+import com.google.gson.JsonObject
 import io.ktor.application.ApplicationCallPipeline
 import io.ktor.application.call
 import io.ktor.application.install
@@ -404,88 +406,99 @@ fun main() {
             post("/bank-transports") {
                 val userId = 
authenticateRequest(call.request.headers["Authorization"])
                 // user exists and is authenticated.
-                val body = call.receive<BankTransport>()
-                logger.debug("Request body parsed")
-                when (body.backup) {
-                    is EbicsKeysBackupJson -> {
-                        logger.debug("Restoring a transport: 
${body.transport.name}")
-                        val (authKey, encKey, sigKey) = try {
-                            Triple(
-                                CryptoUtil.decryptKey(
-                                    
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.authBlob)),
-                                    body.backup.passphrase
-                                ),
-                                CryptoUtil.decryptKey(
-                                    
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.encBlob)),
-                                    body.backup.passphrase
-                                ),
-                                CryptoUtil.decryptKey(
-                                    
EncryptedPrivateKeyInfo(base64ToBytes(body.backup.sigBlob)),
-                                    body.backup.passphrase
-                                )
-                            )
-                        } catch (e: Exception) {
-                            e.printStackTrace()
-                            logger.info("Restoring keys failed, probably due 
to wrong passphrase")
-                            throw NexusError(
-                                HttpStatusCode.BadRequest,
-                                "Bad backup given"
+                val body = call.receive<JsonObject>()
+                val transport: Transport = getTransportFromJsonObject(body)
+                when (transport.type) {
+                    "ebics" -> {
+                        if (body.get("backup") != null) {
+                            val backup = Gson().fromJson(
+                                body.get("backup").asJsonObject,
+                                EbicsKeysBackupJson::class.java
                             )
+                            val (authKey, encKey, sigKey) = try {
+                                Triple(
+                                    CryptoUtil.decryptKey(
+                                        
EncryptedPrivateKeyInfo(base64ToBytes(backup.authBlob)),
+                                        backup.passphrase
+                                    ),
+                                    CryptoUtil.decryptKey(
+                                        
EncryptedPrivateKeyInfo(base64ToBytes(backup.encBlob)),
+                                        backup.passphrase
+                                    ),
+                                    CryptoUtil.decryptKey(
+                                        
EncryptedPrivateKeyInfo(base64ToBytes(backup.sigBlob)),
+                                        backup.passphrase
+                                    )
+                                )
+                            } catch (e: Exception) {
+                                e.printStackTrace()
+                                logger.info("Restoring keys failed, probably 
due to wrong passphrase")
+                                throw NexusError(
+                                    HttpStatusCode.BadRequest,
+                                    "Bad backup given"
+                                )
+                            }
+                            logger.info("Restoring keys, creating new user: 
$userId")
+                            try {
+                                transaction {
+                                    EbicsSubscriberEntity.new(transport.name) {
+                                        this.nexusUser = 
extractNexusUser(userId)
+                                        ebicsURL = backup.ebicsURL
+                                        hostID = backup.hostID
+                                        partnerID = backup.partnerID
+                                        userID = backup.userID
+                                        signaturePrivateKey = 
SerialBlob(sigKey.encoded)
+                                        encryptionPrivateKey = 
SerialBlob(encKey.encoded)
+                                        authenticationPrivateKey = 
SerialBlob(authKey.encoded)
+                                    }
+                                }
+                            } catch (e: Exception) {
+                                print(e)
+                                call.respond(
+                                    NexusErrorJson("Could not store the new 
account into database")
+                                )
+                                return@post
+                            }
+                            call.respondText("Backup restored")
+
+                            return@post
                         }
-                        logger.info("Restoring keys, creating new user: 
$userId")
-                        try {
+                        if (body.get("data") != null) {
+                            val data = Gson().fromJson(
+                                body.get("data"),
+                                EbicsNewTransport::class.java
+                            )
+                            val pairA = CryptoUtil.generateRsaKeyPair(2048)
+                            val pairB = CryptoUtil.generateRsaKeyPair(2048)
+                            val pairC = CryptoUtil.generateRsaKeyPair(2048)
                             transaction {
-                                EbicsSubscriberEntity.new(body.transport.name) 
{
-                                    this.nexusUser = extractNexusUser(userId)
-                                    ebicsURL = body.backup.ebicsURL
-                                    hostID = body.backup.hostID
-                                    partnerID = body.backup.partnerID
-                                    userID = body.backup.userID
-                                    signaturePrivateKey = 
SerialBlob(sigKey.encoded)
-                                    encryptionPrivateKey = 
SerialBlob(encKey.encoded)
-                                    authenticationPrivateKey = 
SerialBlob(authKey.encoded)
+                                EbicsSubscriberEntity.new(transport.name) {
+                                    nexusUser = extractNexusUser(userId)
+                                    ebicsURL = data.ebicsURL
+                                    hostID = data.hostID
+                                    partnerID = data.partnerID
+                                    userID = data.userID
+                                    systemID = data.systemID
+                                    signaturePrivateKey = 
SerialBlob(pairA.private.encoded)
+                                    encryptionPrivateKey = 
SerialBlob(pairB.private.encoded)
+                                    authenticationPrivateKey = 
SerialBlob(pairC.private.encoded)
                                 }
                             }
-                        } catch (e: Exception) {
-                            print(e)
-                            call.respond(
-                                NexusErrorJson("Could not store the new 
account into database")
-                            )
+                            call.respondText("EBICS user successfully created")
                             return@post
                         }
-                        call.respondText("Backup restored")
-                        return@post
+                        throw NexusError(
+                            HttpStatusCode.BadRequest,
+                            "Neither restore or new transport were specified."
+                        )
                     }
-                }
-                when (body.data) {
-                    is EbicsNewTransport -> {
-                        logger.debug("Creating new transport: 
${body.transport.name}")
-                        val pairA = CryptoUtil.generateRsaKeyPair(2048)
-                        val pairB = CryptoUtil.generateRsaKeyPair(2048)
-                        val pairC = CryptoUtil.generateRsaKeyPair(2048)
-                        transaction {
-                            EbicsSubscriberEntity.new(body.transport.name) {
-                                nexusUser = extractNexusUser(userId)
-                                ebicsURL = body.data.ebicsURL
-                                hostID = body.data.hostID
-                                partnerID = body.data.partnerID
-                                userID = body.data.userID
-                                systemID = body.data.systemID
-                                signaturePrivateKey = 
SerialBlob(pairA.private.encoded)
-                                encryptionPrivateKey = 
SerialBlob(pairB.private.encoded)
-                                authenticationPrivateKey = 
SerialBlob(pairC.private.encoded)
-                            }
-                        }
-                        call.respondText("EBICS user successfully created")
-                        return@post
+                    else -> {
+                        throw NexusError(
+                            HttpStatusCode.BadRequest,
+                            "Invalid transport type '${transport.type}'"
+                        )
                     }
-                } // end of second 'when'.
-
-                call.respond(
-                    HttpStatusCode.BadRequest,
-                    "Neither backup nor new transport given in request"
-                )
-                return@post
+                }
             }
             /**
              * Sends to the bank a message "MSG" according to the transport
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
index b259bb5..f3dd614 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/taler.kt
@@ -226,7 +226,7 @@ class Taler(app: Route) {
             val creditorObj = parsePayto(transferRequest.credit_account)
             val opaque_row_id = transaction {
                 val creditorData = parsePayto(transferRequest.credit_account)
-                val exchangeBankAccount = 
getBankAccountFromNexusUserId(exchangeId)
+                val exchangeBankAccount = 
getBankAccountsFromNexusUserId(exchangeId).first()
                 val nexusUser = extractNexusUser(exchangeId)
                 /** Checking the UID has the desired characteristics */
                 TalerRequestedPaymentEntity.find {
@@ -251,9 +251,7 @@ class Taler(app: Route) {
                         subject = transferRequest.wtid,
                         sum = amountObj.amount,
                         currency = amountObj.currency,
-                        debitorName = exchangeBankAccount.accountHolder,
-                        debitorBic = exchangeBankAccount.bankCode,
-                        debitorIban = exchangeBankAccount.iban
+                        debitorAccount = exchangeBankAccount.id.value
                     ),
                     nexusUser
                 )
@@ -264,11 +262,10 @@ class Taler(app: Route) {
                         transactionType = "DBIT"
                         currency = amountObj.currency
                         this.amount = amountObj.amount.toPlainString()
-                        debitorName = "Exchange Company"
-                        debitorIban = exchangeBankAccount.iban
-                        creditorName = creditorObj.name
-                        creditorIban = creditorObj.iban
                         counterpartBic = creditorObj.bic
+                        counterpartIban = creditorObj.iban
+                        counterpartName = creditorObj.name
+                        bankAccount = exchangeBankAccount
                         bookingDate = DateTime.now().millis
                         this.nexusUser = nexusUser
                         status = "BOOK"
@@ -312,21 +309,20 @@ class Taler(app: Route) {
             val debtor = parsePayto(addIncomingData.debit_account)
             val amount = parseAmount(addIncomingData.amount)
             val (bookingDate, opaque_row_id) = transaction {
-                val exchangeBankAccount = 
getBankAccountFromNexusUserId(exchangeId)
+                val exchangeBankAccount = 
getBankAccountsFromNexusUserId(exchangeId).first()
                 val rawPayment = RawBankTransactionEntity.new {
                     sourceFileName = "test"
                     unstructuredRemittanceInformation = 
addIncomingData.reserve_pub
                     transactionType = "CRDT"
                     currency = amount.currency
                     this.amount = amount.amount.toPlainString()
-                    creditorIban = exchangeBankAccount.iban
-                    creditorName = exchangeBankAccount.accountHolder
-                    debitorIban = debtor.iban
-                    debitorName = debtor.name
                     counterpartBic = debtor.bic
+                    counterpartName = debtor.name
+                    counterpartIban = debtor.iban
                     bookingDate = DateTime.now().millis
                     status = "BOOK"
                     nexusUser = extractNexusUser(exchangeId)
+                    bankAccount = exchangeBankAccount
                 }
                 /** This payment is "valid by default" and will be returned
                  * as soon as the exchange will ask for new payments.  */
@@ -355,30 +351,26 @@ class Taler(app: Route) {
          * places it into a further table.  Eventually, another routine will 
perform
          * all the prepared payments.  */
         
app.post("/ebics/taler/{id}/accounts/{acctid}/refund-invalid-payments") {
+            val userId = 
authenticateRequest(call.request.headers["Authorization"])
+            val nexusUser = getNexusUser(userId)
+            val callerBankAccount = expectNonNull(call.parameters["acctid"])
             transaction {
-                val nexusUser = extractNexusUser(call.parameters["id"])
-                val acctid = expectAcctidTransaction(call.parameters["acctid"])
-                if 
(!subscriberHasRights(getEbicsSubscriberFromUser(nexusUser), acctid)) {
-                    throw NexusError(
-                        HttpStatusCode.Forbidden,
-                        "The requester can't drive such account (${acctid.id})"
-                    )
-                }
-                val requesterBankAccount = 
getBankAccountFromNexusUserId(nexusUser.id.value)
+                val bankAccount = getBankAccount(
+                    userId,
+                    callerBankAccount
+                )
                 TalerIncomingPaymentEntity.find {
                     TalerIncomingPayments.refunded eq false and 
(TalerIncomingPayments.valid eq false)
                 }.forEach {
                     addPreparedPayment(
                         Pain001Data(
-                            creditorName = it.payment.debitorName,
-                            creditorIban = it.payment.debitorIban,
+                            creditorName = it.payment.counterpartName,
+                            creditorIban = it.payment.counterpartIban,
                             creditorBic = it.payment.counterpartBic,
                             sum = calculateRefund(it.payment.amount),
                             subject = "Taler refund",
-                            debitorIban = requesterBankAccount.iban,
-                            debitorBic = requesterBankAccount.bankCode,
-                            debitorName = requesterBankAccount.accountHolder,
-                            currency = it.payment.currency
+                            currency = it.payment.currency,
+                            debitorAccount = callerBankAccount
                         ),
                         nexusUser
                     )
@@ -398,18 +390,22 @@ class Taler(app: Route) {
             val id = ensureNonNull(call.parameters["id"])
             // first find highest ID value of already processed rows.
             transaction {
-                val subscriberAccount = getBankAccountFromNexusUserId(id)
+                val subscriberAccount = 
getBankAccountsFromNexusUserId(id).first()
                 /**
                  * Search for fresh incoming payments in the raw table, and 
making pointers
-                 * from the Taler incoming payments table to the found fresh 
payments.
+                 * from the Taler incoming payments table to the found fresh 
(and valid!) payments.
                  */
                 val latestIncomingPaymentId: Long = 
TalerIncomingPaymentEntity.getLast()
                 RawBankTransactionEntity.find {
-                    /** select payments having the exchange as the credited 
party */
-                    RawBankTransactionsTable.creditorIban eq 
subscriberAccount.iban and
+                    /** Those with exchange bank account involved */
+                    RawBankTransactionsTable.bankAccount eq 
subscriberAccount.id.value and
+                            /** Those that are incoming */
+                            (RawBankTransactionsTable.transactionType eq 
"CRDT") and
+                            /** Those that are booked */
                             (RawBankTransactionsTable.status eq "BOOK") and
-                            /** avoid processing old payments from the raw 
table */
+                            /** Those that came later than the latest 
processed payment */
                             
(RawBankTransactionsTable.id.greater(latestIncomingPaymentId))
+
                 }.forEach {
                     if (duplicatePayment(it)) {
                         logger.warn("Incomint payment already seen")
@@ -437,8 +433,12 @@ class Taler(app: Route) {
                  */
                 val latestOutgoingPaymentId = 
TalerRequestedPaymentEntity.getLast()
                 RawBankTransactionEntity.find {
+                    /** Those that came after the last processed payment */
                     RawBankTransactionsTable.id greater 
latestOutgoingPaymentId and
-                            ( RawBankTransactionsTable.debitorIban eq  
subscriberAccount.iban)
+                            /** Those involving the exchange bank account */
+                            (RawBankTransactionsTable.bankAccount eq 
subscriberAccount.id.value) and
+                            /** Those that are outgoing */
+                            (RawBankTransactionsTable.transactionType eq 
"DBIT")
                 }.forEach {
                     if (paymentFailed(it)) {
                         logger.error("Bank didn't accept one payment from the 
exchange")
@@ -485,7 +485,7 @@ class Taler(app: Route) {
             val history = TalerOutgoingHistory()
             transaction {
                 /** Retrieve all the outgoing payments from the _clean Taler 
outgoing table_ */
-                val subscriberBankAccount = 
getBankAccountFromNexusUserId(subscriberId)
+                val subscriberBankAccount = 
getBankAccountsFromNexusUserId(subscriberId).first()
                 val reqPayments = TalerRequestedPaymentEntity.find {
                     TalerRequestedPayments.rawConfirmed.isNotNull() and 
startCmpOp
                 }.orderTaler(delta)
@@ -539,12 +539,12 @@ class Taler(app: Route) {
                         val nexusUser = extractNexusUser(exchangeId)
                         BankAccountMapEntity.new {
                             bankAccount = newBankAccount
-                            ebicsSubscriber = 
getEbicsSubscriberFromUser(nexusUser)
+                            ebicsSubscriber = getEbicsTransport(exchangeId)
                             this.nexusUser = nexusUser
                         }
                     }
                 }
-                val exchangeBankAccount = 
getBankAccountFromNexusUserId(exchangeId)
+                val exchangeBankAccount = 
getBankAccountsFromNexusUserId(exchangeId).first()
                 val orderedPayments = TalerIncomingPaymentEntity.find {
                     TalerIncomingPayments.valid eq true and startCmpOp
                 }.orderTaler(delta)
@@ -556,11 +556,15 @@ class Taler(app: Route) {
                                 row_id = it.id.value,
                                 amount = 
"${it.payment.currency}:${it.payment.amount}",
                                 reserve_pub = 
it.payment.unstructuredRemittanceInformation,
-                                debit_account = buildPaytoUri(
-                                    it.payment.debitorName, 
it.payment.debitorIban, it.payment.counterpartBic
-                                ),
                                 credit_account = buildPaytoUri(
-                                    it.payment.creditorName, 
it.payment.creditorIban, exchangeBankAccount.bankCode
+                                    it.payment.bankAccount.accountHolder,
+                                    it.payment.bankAccount.iban,
+                                    it.payment.bankAccount.bankCode
+                                ),
+                                debit_account = buildPaytoUri(
+                                    it.payment.counterpartName,
+                                    it.payment.counterpartIban,
+                                    it.payment.counterpartBic
                                 )
                             )
                         )
diff --git a/nexus/src/test/kotlin/PainGeneration.kt 
b/nexus/src/test/kotlin/PainGeneration.kt
index e257c50..82b1470 100644
--- a/nexus/src/test/kotlin/PainGeneration.kt
+++ b/nexus/src/test/kotlin/PainGeneration.kt
@@ -31,9 +31,7 @@ class PainTest {
                 creditorBic = "CREDIT BIC"
                 creditorName = "CREDIT NAME"
                 paymentId = 1
-                msgId = 1
                 endToEndId = 1
-                date = DateTime.now().millis
                 nexusUser = NexusUserEntity.new(id = "mock") { }
             }
         }
diff --git a/nexus/src/test/kotlin/taler.kt b/nexus/src/test/kotlin/taler.kt
index d582a97..cd7c327 100644
--- a/nexus/src/test/kotlin/taler.kt
+++ b/nexus/src/test/kotlin/taler.kt
@@ -2,15 +2,13 @@ package tech.libeufin.nexus
 
 import io.ktor.routing.RootRouteSelector
 import io.ktor.routing.Route
-import io.ktor.routing.RouteSelector
-import io.ktor.routing.RouteSelectorEvaluation
 import io.ktor.util.InternalAPI
-import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
-import tech.libeufin.nexus.Taler
 import tech.libeufin.util.Amount
 import java.math.BigDecimal
 
+/*
 class TalerTest {
 
     @InternalAPI
@@ -35,4 +33,6 @@ class TalerTest {
         val amount25 = taler.parseAmount("EUR:2.5")
         assert(amount25.amount.compareTo(Amount("2.5")) == 0)
     }
-}
\ No newline at end of file
+}
+
+ */
\ No newline at end of file
diff --git a/util/src/main/kotlin/ParametersChecks.kt 
b/util/src/main/kotlin/ParametersChecks.kt
index cc910b4..abf5bc2 100644
--- a/util/src/main/kotlin/ParametersChecks.kt
+++ b/util/src/main/kotlin/ParametersChecks.kt
@@ -11,6 +11,13 @@ fun expectInt(param: String): Int {
     }
 }
 
+fun <T>expectNonNull(param: T?): T {
+    return param ?: throw UtilError(
+        HttpStatusCode.BadRequest,
+        "Non-null value expected."
+    )
+}
+
 fun expectLong(param: String): Long {
     return try {
         param.toLong()

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



reply via email to

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