diff options
author | Antoine A <> | 2024-02-13 20:35:04 +0100 |
---|---|---|
committer | Antoine A <> | 2024-02-13 20:39:29 +0100 |
commit | 3d1dfce83bf74917886a5f3cc55aa7f97b74aac4 (patch) | |
tree | 5b6f2863451e3dd62fb5267a33c0753fa4770729 /bank | |
parent | 3046601e239d774716527d4a0a34f585ac5ade79 (diff) | |
download | libeufin-3d1dfce83bf74917886a5f3cc55aa7f97b74aac4.tar.gz libeufin-3d1dfce83bf74917886a5f3cc55aa7f97b74aac4.tar.bz2 libeufin-3d1dfce83bf74917886a5f3cc55aa7f97b74aac4.zip |
Code cleanup
Diffstat (limited to 'bank')
39 files changed, 345 insertions, 360 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt index f5477896..17d2a917 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/BankIntegrationApi.kt @@ -21,15 +21,15 @@ * that are typically requested by wallets. */ package tech.libeufin.bank +import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import io.ktor.http.* +import tech.libeufin.bank.db.AbortResult +import tech.libeufin.bank.db.Database +import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalSelectionResult import tech.libeufin.common.TalerErrorCode -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.WithdrawalDAO.* -import java.lang.AssertionError fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) { get("/taler-integration/config") { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt index 2c15f43b..42df06b4 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt @@ -18,14 +18,12 @@ */ package tech.libeufin.bank -import tech.libeufin.common.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import tech.libeufin.common.DatabaseConfig -import java.nio.file.* -import kotlin.io.path.* import org.slf4j.Logger import org.slf4j.LoggerFactory +import tech.libeufin.common.* +import java.nio.file.Path private val logger: Logger = LoggerFactory.getLogger("libeufin-bank") @@ -89,11 +87,11 @@ fun TalerConfig.loadServerConfig(): ServerConfig { fun TalerConfig.loadBankConfig(): BankConfig { val regionalCurrency = requireString("libeufin-bank", "currency") - var fiatCurrency: String? = null; + var fiatCurrency: String? = null var fiatCurrencySpec: CurrencySpecification? = null - val allowConversion = lookupBoolean("libeufin-bank", "allow_conversion") ?: false; + val allowConversion = lookupBoolean("libeufin-bank", "allow_conversion") ?: false if (allowConversion) { - fiatCurrency = requireString("libeufin-bank", "fiat_currency"); + fiatCurrency = requireString("libeufin-bank", "fiat_currency") fiatCurrencySpec = currencySpecificationFor(fiatCurrency) } val tanChannels = buildMap { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt index 1a746488..8bb59bc2 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Constants.kt @@ -18,23 +18,23 @@ */ package tech.libeufin.bank -import tech.libeufin.common.* +import tech.libeufin.common.ConfigSource import java.time.Duration // Config val BANK_CONFIG_SOURCE = ConfigSource("libeufin", "libeufin-bank", "libeufin-bank") // TAN -const val TAN_RETRY_COUNTER: Int = 3; +const val TAN_RETRY_COUNTER: Int = 3 val TAN_VALIDITY_PERIOD: Duration = Duration.ofHours(1) val TAN_RETRANSMISSION_PERIOD: Duration = Duration.ofMinutes(1) // Token -val TOKEN_DEFAULT_DURATION: java.time.Duration = Duration.ofDays(1L) +val TOKEN_DEFAULT_DURATION: Duration = Duration.ofDays(1L) // Account val RESERVED_ACCOUNTS = setOf("admin", "bank") -const val IBAN_ALLOCATION_RETRY_COUNTER: Int = 5; +const val IBAN_ALLOCATION_RETRY_COUNTER: Int = 5 // Security const val MAX_BODY_LENGTH: Long = 4 * 1024 // 4kB diff --git a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt index 6707eff0..168b2034 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/ConversionApi.kt @@ -23,11 +23,12 @@ import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import java.util.* -import tech.libeufin.common.* -import tech.libeufin.bank.auth.* -import tech.libeufin.bank.db.ConversionDAO.* -import tech.libeufin.bank.db.* +import tech.libeufin.bank.auth.authAdmin +import tech.libeufin.bank.db.ConversionDAO +import tech.libeufin.bank.db.ConversionDAO.ConversionResult +import tech.libeufin.bank.db.Database +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode fun Routing.conversionApi(db: Database, ctx: BankConfig) = conditional(ctx.allowConversion) { get("/conversion-info/config") { @@ -108,7 +109,7 @@ fun Routing.conversionApi(db: Database, ctx: BankConfig) = conditional(ctx.allow for (fiatAmount in sequenceOf(req.cashout_fee, req.cashout_tiny_amount, req.cashin_min_amount)) { ctx.checkFiatCurrency(fiatAmount) } - db.conversion.updateConfig(req); + db.conversion.updateConfig(req) call.respond(HttpStatusCode.NoContent) } } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt index 6dab5571..5d7646ce 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/CoreBankApi.kt @@ -23,27 +23,27 @@ import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import java.time.Duration -import java.time.Instant -import java.time.temporal.ChronoUnit -import java.util.* -import kotlin.random.Random -import kotlinx.serialization.json.Json import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.future.await import kotlinx.coroutines.withContext import org.slf4j.Logger import org.slf4j.LoggerFactory -import tech.libeufin.bank.* import tech.libeufin.bank.auth.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.TanDAO.* +import tech.libeufin.bank.db.AbortResult import tech.libeufin.bank.db.AccountDAO.* -import tech.libeufin.bank.db.CashoutDAO.* -import tech.libeufin.bank.db.ExchangeDAO.* -import tech.libeufin.bank.db.TransactionDAO.* -import tech.libeufin.bank.db.WithdrawalDAO.* +import tech.libeufin.bank.db.CashoutDAO.CashoutCreationResult +import tech.libeufin.bank.db.Database +import tech.libeufin.bank.db.TanDAO.TanSendResult +import tech.libeufin.bank.db.TanDAO.TanSolveResult +import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult +import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalConfirmationResult +import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult import tech.libeufin.common.* +import java.time.Duration +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.* +import kotlin.random.Random private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-api") @@ -293,7 +293,7 @@ private fun Routing.coreBankAccountsApi(db: Database, ctx: BankConfig) { authAdmin(db, TokenScope.readwrite, !ctx.allowRegistration) { post("/accounts") { val req = call.receive<RegisterAccountRequest>() - val (result, internalPayto) = createAccount(db, ctx, req, isAdmin); + val (result, internalPayto) = createAccount(db, ctx, req, isAdmin) when (result) { AccountCreationResult.BonusBalanceInsufficient -> throw conflict( "Insufficient admin funds to grant bonus", diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt index 7fd4c3b5..f6c83224 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt @@ -19,11 +19,13 @@ package tech.libeufin.bank import io.ktor.http.* +import io.ktor.server.application.* import io.ktor.server.response.* -import io.ktor.server.application.ApplicationCall -import io.ktor.util.AttributeKey +import io.ktor.util.* import kotlinx.serialization.Serializable -import tech.libeufin.common.* +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode + /** * Convenience type to throw errors along the bank activity * and that is meant to be caught by Ktor and responded to the @@ -50,7 +52,7 @@ data class TalerError( val detail: String? = null ) -private val LOG_MSG = AttributeKey<String>("log_msg"); +private val LOG_MSG = AttributeKey<String>("log_msg") fun ApplicationCall.logMsg(): String? = attributes.getOrNull(LOG_MSG) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt index f0d8ac89..e6245238 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -21,41 +21,46 @@ package tech.libeufin.bank import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands -import com.github.ajalt.clikt.parameters.types.* -import com.github.ajalt.clikt.parameters.arguments.* +import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.arguments.convert +import com.github.ajalt.clikt.parameters.arguments.optional +import com.github.ajalt.clikt.parameters.groups.OptionGroup +import com.github.ajalt.clikt.parameters.groups.cooccurring +import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* -import com.github.ajalt.clikt.parameters.groups.* +import com.github.ajalt.clikt.parameters.types.boolean import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.http.content.* import io.ktor.serialization.kotlinx.json.* +import io.ktor.server.application.* import io.ktor.server.engine.* +import io.ktor.server.http.content.* import io.ktor.server.netty.* import io.ktor.server.plugins.* import io.ktor.server.plugins.callloging.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.cors.routing.* -import io.ktor.server.plugins.statuspages.* import io.ktor.server.plugins.forwardedheaders.* +import io.ktor.server.plugins.statuspages.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.utils.io.* -import java.time.Duration -import java.util.zip.DataFormatException -import java.util.zip.Inflater -import java.sql.SQLException -import kotlinx.coroutines.* +import kotlinx.coroutines.runBlocking import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.* +import kotlinx.serialization.json.Json +import org.postgresql.util.PSQLState import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level -import org.postgresql.util.PSQLState import tech.libeufin.bank.db.AccountDAO.* -import tech.libeufin.bank.db.* +import tech.libeufin.bank.db.Database import tech.libeufin.common.* -import kotlin.io.path.* +import java.sql.SQLException +import java.util.zip.DataFormatException +import java.util.zip.Inflater +import kotlin.io.path.Path +import kotlin.io.path.exists +import kotlin.io.path.readText private val logger: Logger = LoggerFactory.getLogger("libeufin-bank") // Dirty local variable to stop the server in test TODO remove this ugly hack @@ -69,7 +74,7 @@ val bodyPlugin = createApplicationPlugin("BodyLimitAndDecompression") { // TODO check content length as an optimisation transformBody { body -> val bytes = ByteArray(MAX_BODY_LENGTH.toInt() + 1) - var read = 0; + var read = 0 when (val encoding = call.request.headers[HttpHeaders.ContentEncoding]) { "deflate" -> { // Decompress and check decompressed length @@ -95,7 +100,7 @@ val bodyPlugin = createApplicationPlugin("BodyLimitAndDecompression") { // Check body length while (true) { val new = body.readAvailable(bytes, read, bytes.size - read) - if (new == -1) break; // Channel is closed + if (new == -1) break // Channel is closed read += new if (read > MAX_BODY_LENGTH) throw badRequest("Body is suspiciously big > $MAX_BODY_LENGTH B") @@ -239,7 +244,7 @@ class BankDbInit : CliktCommand("Initialize the libeufin-bank database", name = override fun run() = cliCmd(logger, common.log) { val config = talerConfig(common.config) val cfg = config.loadDbConfig() - val ctx = config.loadBankConfig(); + val ctx = config.loadBankConfig() Database(cfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency).use { db -> runBlocking { db.conn { conn -> @@ -480,7 +485,7 @@ class CreateAccount : CliktCommand( ) } req?.let { - val (result, internalPayto) = createAccount(db, ctx, req, true); + val (result, internalPayto) = createAccount(db, ctx, req, true) when (result) { AccountCreationResult.BonusBalanceInsufficient -> throw Exception("Insufficient admin funds to grant bonus") diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt b/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt index 4c1a13d7..8bfbe80c 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Metadata.kt @@ -21,7 +21,7 @@ package tech.libeufin.bank private val PATTERN = Regex("[a-z0-9A-Z]{52}") fun parseIncomingTxMetadata(subject: String): EddsaPublicKey? { - val match = PATTERN.find(subject)?.value ?: return null; + val match = PATTERN.find(subject)?.value ?: return null try { return EddsaPublicKey(match) } catch (e: Exception) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt b/bank/src/main/kotlin/tech/libeufin/bank/Params.kt index 7b3e53e8..59210164 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Params.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Params.kt @@ -20,14 +20,11 @@ package tech.libeufin.bank import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.plugins.* -import io.ktor.server.request.* -import io.ktor.server.util.* -import java.time.* -import java.time.temporal.* -import java.util.* -import tech.libeufin.common.* +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.time.temporal.TemporalAdjusters fun Parameters.expect(name: String): String = get(name) ?: throw badRequest("Missing '$name' parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) @@ -53,10 +50,10 @@ data class MonitorParams( val which: Int? ) { companion object { - val names = Timeframe.values().map { it.name } + val names = Timeframe.entries.map { it.name } val names_fmt = names.joinToString() fun extract(params: Parameters): MonitorParams { - val raw = params.get("timeframe") ?: "hour"; + val raw = params.get("timeframe") ?: "hour" if (!names.contains(raw)) { throw badRequest("Param 'timeframe' must be one of $names_fmt", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } @@ -150,10 +147,10 @@ data class StatusParams( val old_state: WithdrawalStatus ) { companion object { - val names = WithdrawalStatus.values().map { it.name } + val names = WithdrawalStatus.entries.map { it.name } val names_fmt = names.joinToString() fun extract(params: Parameters): StatusParams { - val old_state = params.get("old_state") ?: "pending"; + val old_state = params.get("old_state") ?: "pending" if (!names.contains(old_state)) { throw badRequest("Param 'old_state' must be one of $names_fmt", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt index 9009e1a5..fe16a23c 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/RevenueApi.kt @@ -20,13 +20,10 @@ package tech.libeufin.bank import io.ktor.http.* import io.ktor.server.application.* -import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import java.util.* -import tech.libeufin.common.* -import tech.libeufin.bank.auth.* -import tech.libeufin.bank.db.* +import tech.libeufin.bank.auth.auth +import tech.libeufin.bank.db.Database fun Routing.revenueApi(db: Database, ctx: BankConfig) { auth(db, TokenScope.readonly) { @@ -38,8 +35,8 @@ fun Routing.revenueApi(db: Database, ctx: BankConfig) { get("/accounts/{USERNAME}/taler-revenue/history") { val params = HistoryParams.extract(context.request.queryParameters) val bankAccount = call.bankInfo(db, ctx.payto) - val items = db.transaction.revenueHistory(params, bankAccount.bankAccountId, ctx.payto); - + val items = db.transaction.revenueHistory(params, bankAccount.bankAccountId, ctx.payto) + if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt b/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt index 77a67274..de0ebc20 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/TalerCommon.kt @@ -19,20 +19,25 @@ package tech.libeufin.bank -import tech.libeufin.common.* -import io.ktor.http.* -import io.ktor.serialization.kotlinx.json.* -import io.ktor.server.application.* -import java.net.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.longOrNull +import tech.libeufin.common.Base32Crockford +import tech.libeufin.common.EncodingException +import tech.libeufin.common.TalerAmount +import java.net.URL import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit -import java.util.* import java.util.concurrent.TimeUnit -import kotlinx.serialization.* -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* -import kotlinx.serialization.json.* /** 32-byte Crockford's Base32 encoded data */ @Serializable(with = Base32Crockford32B.Serializer::class) @@ -141,20 +146,20 @@ class Base32Crockford64B { } /** 32-byte hash code */ -typealias ShortHashCode = Base32Crockford32B; +typealias ShortHashCode = Base32Crockford32B /** 64-byte hash code */ -typealias HashCode = Base32Crockford64B; +typealias HashCode = Base32Crockford64B /** * EdDSA and ECDHE public keys always point on Curve25519 * and represented using the standard 256 bits Ed25519 compact format, * converted to Crockford Base32. */ -typealias EddsaPublicKey = Base32Crockford32B; +typealias EddsaPublicKey = Base32Crockford32B /** Timestamp containing the number of seconds since epoch */ @Serializable data class TalerProtocolTimestamp( - @Serializable(with = TalerProtocolTimestamp.Serializer::class) + @Serializable(with = Serializer::class) val t_s: Instant, ) { companion object { @@ -186,7 +191,7 @@ data class TalerProtocolTimestamp( ?: throw badRequest("Could not convert t_s '${maybeTs.content}' to a number") when { ts < 0 -> throw badRequest("Negative timestamp not allowed") - ts > Instant.MAX.getEpochSecond() -> throw badRequest("Timestamp $ts too big to be represented in Kotlin") + ts > Instant.MAX.epochSecond -> throw badRequest("Timestamp $ts too big to be represented in Kotlin") else -> return Instant.ofEpochSecond(ts) } } @@ -205,7 +210,7 @@ class DecimalNumber { this.frac = frac } constructor(encoded: String) { - val match = PATTERN.matchEntire(encoded) ?: throw badRequest("Invalid decimal number format"); + val match = PATTERN.matchEntire(encoded) ?: throw badRequest("Invalid decimal number format") val (value, frac) = match.destructured this.value = value.toLongOrNull() ?: throw badRequest("Invalid value") if (this.value > TalerAmount.MAX_VALUE) throw badRequest("Value specified in decimal number is too large") @@ -249,7 +254,7 @@ class DecimalNumber { } companion object { - private val PATTERN = Regex("([0-9]+)(?:\\.([0-9]{1,8}))?"); + private val PATTERN = Regex("([0-9]+)(?:\\.([0-9]{1,8}))?") } } @@ -260,7 +265,7 @@ class DecimalNumber { */ @Serializable() data class RelativeTime( - @Serializable(with = RelativeTime.Serializer::class) + @Serializable(with = Serializer::class) val d_us: Duration ) { internal object Serializer : KSerializer<Duration> { @@ -292,7 +297,7 @@ data class RelativeTime( } companion object { - private const val MAX_SAFE_INTEGER = 9007199254740991L; // 2^53 - 1 + private const val MAX_SAFE_INTEGER = 9007199254740991L // 2^53 - 1 } } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt index 6f926c10..5f98ae07 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt @@ -19,18 +19,17 @@ package tech.libeufin.bank -import tech.libeufin.common.* -import io.ktor.http.* -import io.ktor.server.application.* -import kotlinx.serialization.* -import java.time.Duration -import java.time.Instant -import java.time.temporal.ChronoUnit -import java.util.* +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import tech.libeufin.common.IbanPayto +import tech.libeufin.common.Payto +import tech.libeufin.common.TalerAmount +import java.time.Instant /** * Allowed lengths for fractional digits in amounts. @@ -92,18 +91,18 @@ sealed class Option<out T> { fun get(): T? { return when (this) { - Option.None -> null - is Option.Some -> this.value + None -> null + is Some -> this.value } } inline fun some(lambda: (T) -> Unit) { - if (this is Option.Some) { + if (this is Some) { lambda(value) } } - fun isSome(): Boolean = this is Option.Some + fun isSome(): Boolean = this is Some @OptIn(ExperimentalSerializationApi::class) internal class Serializer<T> ( @@ -113,13 +112,13 @@ sealed class Option<out T> { override fun serialize(encoder: Encoder, value: Option<T>) { when (value) { - Option.None -> encoder.encodeNull() - is Option.Some -> valueSerializer.serialize(encoder, value.value) + None -> encoder.encodeNull() + is Some -> valueSerializer.serialize(encoder, value.value) } } override fun deserialize(decoder: Decoder): Option<T> { - return Option.Some(valueSerializer.deserialize(decoder)) + return Some(valueSerializer.deserialize(decoder)) } } } @@ -156,10 +155,10 @@ data class ChallengeContactData( val phone: Option<String?> = Option.None ) { init { - if (email.get()?.let { !EMAIL_PATTERN.matches(it) } ?: false) + if (email.get()?.let { !EMAIL_PATTERN.matches(it) } == true) throw badRequest("email contact data '$email' is malformed") - if (phone.get()?.let { !PHONE_PATTERN.matches(it) } ?: false) + if (phone.get()?.let { !PHONE_PATTERN.matches(it) } == true) throw badRequest("phone contact data '$phone' is malformed") } companion object { @@ -215,10 +214,10 @@ data class TokenRequest( @Serializable sealed interface MonitorResponse { - abstract val talerInCount: Long - abstract val talerInVolume: TalerAmount - abstract val talerOutCount: Long - abstract val talerOutVolume: TalerAmount + val talerInCount: Long + val talerInVolume: TalerAmount + val talerOutCount: Long + val talerOutVolume: TalerAmount } @Serializable diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Tan.kt b/bank/src/main/kotlin/tech/libeufin/bank/Tan.kt index 5dddd807..eadddc29 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/Tan.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/Tan.kt @@ -18,29 +18,27 @@ */ package tech.libeufin.bank -import java.security.SecureRandom -import java.time.Instant -import java.time.Duration -import java.text.DecimalFormat -import kotlinx.serialization.json.Json import io.ktor.http.* +import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* -import io.ktor.server.application.* -import tech.libeufin.bank.db.TanDAO.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.auth.* -import io.ktor.util.pipeline.PipelineContext +import kotlinx.serialization.json.Json +import tech.libeufin.bank.auth.username +import tech.libeufin.bank.db.Database +import tech.libeufin.bank.db.TanDAO.Challenge +import java.security.SecureRandom +import java.text.DecimalFormat +import java.time.Instant -inline suspend fun <reified B> ApplicationCall.respondChallenge( +suspend inline fun <reified B> ApplicationCall.respondChallenge( db: Database, op: Operation, body: B, channel: TanChannel? = null, info: String? = null ) { - val json = Json.encodeToString(kotlinx.serialization.serializer<B>(), body); + val json = Json.encodeToString(kotlinx.serialization.serializer<B>(), body) val code = Tan.genCode() val id = db.tan.new( login = username, @@ -59,7 +57,7 @@ inline suspend fun <reified B> ApplicationCall.respondChallenge( ) } -inline suspend fun <reified B> ApplicationCall.receiveChallenge( +suspend inline fun <reified B> ApplicationCall.receiveChallenge( db: Database, op: Operation ): Pair<B, Challenge?> { @@ -85,7 +83,7 @@ suspend fun ApplicationCall.challenge( } object Tan { - private val CODE_FORMAT = DecimalFormat("00000000"); + private val CODE_FORMAT = DecimalFormat("00000000") private val SECURE_RNG = SecureRandom() fun genCode(): String { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt index 0a197422..92a0390d 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/WireGatewayApi.kt @@ -26,12 +26,17 @@ import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -import io.ktor.util.pipeline.PipelineContext +import io.ktor.util.pipeline.* +import tech.libeufin.bank.auth.auth +import tech.libeufin.bank.auth.authAdmin +import tech.libeufin.bank.auth.username +import tech.libeufin.bank.db.Database +import tech.libeufin.bank.db.ExchangeDAO +import tech.libeufin.bank.db.ExchangeDAO.AddIncomingResult +import tech.libeufin.bank.db.ExchangeDAO.TransferResult +import tech.libeufin.common.BankPaytoCtx +import tech.libeufin.common.TalerErrorCode import java.time.Instant -import tech.libeufin.common.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.ExchangeDAO.* -import tech.libeufin.bank.auth.* fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { @@ -94,8 +99,8 @@ fun Routing.wireGatewayApi(db: Database, ctx: BankConfig) { TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE ) - val items = db.exchange.dbLambda(params, bankAccount.bankAccountId, ctx.payto); - + val items = db.exchange.dbLambda(params, bankAccount.bankAccountId, ctx.payto) + if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt index 93baecc5..425af5e8 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt @@ -21,20 +21,20 @@ package tech.libeufin.bank.auth import io.ktor.http.* import io.ktor.server.application.* -import io.ktor.server.routing.Route -import io.ktor.server.response.header -import io.ktor.util.AttributeKey -import io.ktor.util.pipeline.PipelineContext -import java.time.Instant -import tech.libeufin.bank.db.AccountDAO.* -import tech.libeufin.bank.db.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import io.ktor.util.* +import io.ktor.util.pipeline.* import tech.libeufin.bank.* +import tech.libeufin.bank.db.Database import tech.libeufin.common.* +import java.time.Instant /** Used to store if the currenly authenticated user is admin */ -private val AUTH_IS_ADMIN = AttributeKey<Boolean>("is_admin"); +private val AUTH_IS_ADMIN = AttributeKey<Boolean>("is_admin") + /** Used to store used auth token */ -private val AUTH_TOKEN = AttributeKey<ByteArray>("auth_token"); +private val AUTH_TOKEN = AttributeKey<ByteArray>("auth_token") /** Get username of the request account */ val ApplicationCall.username: String get() = expectParameter("USERNAME") @@ -89,7 +89,7 @@ fun Route.auth(db: Database, scope: TokenScope, allowAdmin: Boolean = false, req if (requireAdmin && authLogin != "admin") { throw unauthorized("Only administrator allowed") } else { - val hasRight = authLogin == username || (allowAdmin && authLogin == "admin"); + val hasRight = authLogin == username || (allowAdmin && authLogin == "admin") if (!hasRight) { throw unauthorized("Customer $authLogin have no right on $username account") } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt index e172ea78..18432e59 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt @@ -19,10 +19,9 @@ package tech.libeufin.bank.db -import tech.libeufin.common.* -import java.time.* -import java.sql.Types import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.time.Instant /** Data access logic for accounts */ class AccountDAO(private val db: Database) { @@ -51,7 +50,7 @@ class AccountDAO(private val db: Database) { // Whether to check [internalPaytoUri] for idempotency checkPaytoIdempotent: Boolean ): AccountCreationResult = db.serializable { it -> - val now = Instant.now().toDbMicros() ?: throw faultyTimestampByBank(); + val now = Instant.now().toDbMicros() ?: throw faultyTimestampByBank() it.transaction { conn -> val idempotent = conn.prepareStatement(""" SELECT password_hash, name=? diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt index 2033e101..3f044ea1 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt @@ -19,11 +19,9 @@ package tech.libeufin.bank.db -import java.time.Duration -import java.time.Instant -import java.util.concurrent.TimeUnit -import tech.libeufin.common.* import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.time.Instant /** Data access logic for cashout operations */ class CashoutDAO(private val db: Database) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt index bb311eba..a76b7630 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt @@ -19,9 +19,14 @@ package tech.libeufin.bank.db -import tech.libeufin.common.* -import tech.libeufin.bank.* -import tech.libeufin.bank.* +import tech.libeufin.bank.ConversionRate +import tech.libeufin.bank.DecimalNumber +import tech.libeufin.bank.RoundingMode +import tech.libeufin.bank.internalServerError +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.getAmount +import tech.libeufin.common.oneOrNull +import tech.libeufin.common.transaction /** Data access logic for conversion */ class ConversionDAO(private val db: Database) { @@ -68,8 +73,8 @@ class ConversionDAO(private val db: Database) { it.transaction { conn -> val check = conn.prepareStatement("select exists(select 1 from config where key='cashin_ratio')").oneOrNull { it.getBoolean(1) }!! if (!check) return@transaction null - val amount = conn.prepareStatement("SELECT (amount).val as amount_val, (amount).frac as amount_frac FROM config_get_amount(?) as amount"); - val roundingMode = conn.prepareStatement("SELECT config_get_rounding_mode(?)"); + val amount = conn.prepareStatement("SELECT (amount).val as amount_val, (amount).frac as amount_frac FROM config_get_amount(?) as amount") + val roundingMode = conn.prepareStatement("SELECT config_get_rounding_mode(?)") fun getAmount(name: String, currency: String): TalerAmount { amount.setString(1, name) return amount.oneOrNull { it.getAmount("amount", currency) }!! diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt index 91262ce5..1880b67b 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt @@ -19,21 +19,19 @@ package tech.libeufin.bank.db -import org.postgresql.jdbc.PgConnection -import org.postgresql.ds.PGSimpleDataSource -import org.postgresql.util.PSQLState +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withTimeoutOrNull import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.sql.* -import java.time.* -import java.util.* -import java.util.concurrent.TimeUnit -import kotlin.math.abs -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.* -import tech.libeufin.common.* -import io.ktor.http.HttpStatusCode import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.sql.PreparedStatement +import java.sql.ResultSet +import java.sql.Types +import kotlin.math.abs private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-db") @@ -95,7 +93,7 @@ class Database(dbConfig: String, internal val bankCurrency: String, internal val if (params.which != null) { stmt.setInt(2, params.which) } else { - stmt.setNull(2, java.sql.Types.INTEGER) + stmt.setNull(2, Types.INTEGER) } stmt.oneOrNull { fiatCurrency?.run { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt index a8d926f9..af4639df 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt @@ -19,12 +19,12 @@ package tech.libeufin.bank.db -import java.util.UUID -import java.time.Instant -import java.time.Duration -import java.util.concurrent.TimeUnit -import tech.libeufin.common.* import tech.libeufin.bank.* +import tech.libeufin.common.BankPaytoCtx +import tech.libeufin.common.getAmount +import tech.libeufin.common.getBankPayto +import tech.libeufin.common.toDbMicros +import java.time.Instant /** Data access logic for exchange specific logic */ class ExchangeDAO(private val db: Database) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt index eb6cd879..ab8814b4 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt @@ -19,15 +19,15 @@ package tech.libeufin.bank.db -import java.util.UUID -import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.postgresql.ds.PGSimpleDataSource import org.slf4j.Logger import org.slf4j.LoggerFactory -import tech.libeufin.common.* import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.util.* +import java.util.concurrent.ConcurrentHashMap private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-db-watcher") @@ -115,18 +115,18 @@ internal class NotificationWatcher(private val pgSource: PGSimpleDataSource) { private suspend fun <R, K, V> listen(map: ConcurrentHashMap<K, CountedSharedFlow<V>>, key: K, lambda: suspend (Flow<V>) -> R): R { // Register listener, create a new flow if missing val flow = map.compute(key) { _, v -> - val tmp = v ?: CountedSharedFlow(MutableSharedFlow(), 0); - tmp.count++; + val tmp = v ?: CountedSharedFlow(MutableSharedFlow(), 0) + tmp.count++ tmp - }!!.flow; + }!!.flow try { return lambda(flow) } finally { // Unregister listener, removing unused flow map.compute(key) { _, v -> - v!!; - v.count--; + v!! + v.count-- if (v.count > 0) v else null } } diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt index 46692204..9017540d 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt @@ -19,12 +19,14 @@ package tech.libeufin.bank.db -import tech.libeufin.common.* -import tech.libeufin.bank.* -import tech.libeufin.bank.db.* -import java.util.concurrent.TimeUnit +import tech.libeufin.bank.Operation +import tech.libeufin.bank.TanChannel +import tech.libeufin.bank.internalServerError +import tech.libeufin.common.oneOrNull +import tech.libeufin.common.toDbMicros import java.time.Duration import java.time.Instant +import java.util.concurrent.TimeUnit /** Data access logic for tan challenged */ class TanDAO(private val db: Database) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt index 92708308..8a5c594c 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt @@ -19,9 +19,13 @@ package tech.libeufin.bank.db -import tech.libeufin.common.* +import tech.libeufin.bank.BearerToken +import tech.libeufin.bank.TokenScope +import tech.libeufin.common.executeUpdateViolation +import tech.libeufin.common.microsToJavaInstant +import tech.libeufin.common.oneOrNull +import tech.libeufin.common.toDbMicros import java.time.Instant -import tech.libeufin.bank.* /** Data access logic for auth tokens */ class TokenDAO(private val db: Database) { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt index f3c8cd30..be427b66 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt @@ -21,10 +21,9 @@ package tech.libeufin.bank.db import org.slf4j.Logger import org.slf4j.LoggerFactory -import tech.libeufin.common.* -import java.time.* -import java.sql.Types import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.time.Instant private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-tx-dao") @@ -50,7 +49,7 @@ class TransactionDAO(private val db: Database) { timestamp: Instant, is2fa: Boolean ): BankTransactionResult = db.serializable { conn -> - val now = timestamp.toDbMicros() ?: throw faultyTimestampByBank(); + val now = timestamp.toDbMicros() ?: throw faultyTimestampByBank() conn.transaction { val stmt = conn.prepareStatement(""" SELECT diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt index 12977610..330006a1 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt @@ -19,14 +19,14 @@ package tech.libeufin.bank.db -import java.util.UUID -import java.time.Instant -import java.time.Duration -import java.util.concurrent.TimeUnit -import tech.libeufin.common.* -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.* +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.withTimeoutOrNull import tech.libeufin.bank.* +import tech.libeufin.common.* +import java.time.Instant +import java.util.* /** Data access logic for withdrawal operations */ class WithdrawalDAO(private val db: Database) { @@ -213,7 +213,7 @@ class WithdrawalDAO(private val db: Database) { // Initial loading val init = load() // Long polling if there is no operation or its not confirmed - if (init?.run { status(this) == params.old_state } ?: true) { + if (init?.run { status(this) == params.old_state } != false) { polling.join() load() } else { diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt index 39d21cf4..dd827f2b 100644 --- a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt +++ b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -23,23 +23,21 @@ import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.plugins.* import io.ktor.server.request.* -import io.ktor.server.routing.Route -import io.ktor.server.routing.RouteSelector -import io.ktor.server.routing.RouteSelectorEvaluation -import io.ktor.server.routing.RoutingResolveContext +import io.ktor.server.routing.* import io.ktor.server.util.* -import io.ktor.util.pipeline.PipelineContext -import kotlinx.serialization.* -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* -import java.net.* -import java.time.* -import java.time.temporal.* -import java.util.* +import io.ktor.util.pipeline.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import tech.libeufin.bank.auth.username +import tech.libeufin.bank.db.AccountDAO.AccountCreationResult +import tech.libeufin.bank.db.Database import tech.libeufin.common.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.AccountDAO.* -import tech.libeufin.bank.auth.* +import java.util.* fun ApplicationCall.expectParameter(name: String) = parameters[name] ?: throw badRequest( @@ -108,7 +106,7 @@ fun ApplicationCall.longParameter(name: String): Long { * It returns false in case of problems, true otherwise. */ suspend fun createAdminAccount(db: Database, cfg: BankConfig, pw: String? = null): AccountCreationResult { - var pwStr = pw; + var pwStr = pw if (pwStr == null) { val pwBuf = ByteArray(32) Random().nextBytes(pwBuf) diff --git a/bank/src/test/kotlin/AmountTest.kt b/bank/src/test/kotlin/AmountTest.kt index 5f51b5ad..94716208 100644 --- a/bank/src/test/kotlin/AmountTest.kt +++ b/bank/src/test/kotlin/AmountTest.kt @@ -17,16 +17,14 @@ * <http://www.gnu.org/licenses/> */ -import java.time.Instant -import java.util.* -import kotlin.test.* import org.junit.Test -import org.postgresql.jdbc.PgConnection -import tech.libeufin.bank.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.TransactionDAO.* -import tech.libeufin.bank.db.WithdrawalDAO.* +import tech.libeufin.bank.DecimalNumber +import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult +import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult import tech.libeufin.common.* +import java.time.Instant +import java.util.* +import kotlin.test.assertEquals class AmountTest { // Test amount computation in database diff --git a/bank/src/test/kotlin/BankIntegrationApiTest.kt b/bank/src/test/kotlin/BankIntegrationApiTest.kt index 5f516525..f84c382c 100644 --- a/bank/src/test/kotlin/BankIntegrationApiTest.kt +++ b/bank/src/test/kotlin/BankIntegrationApiTest.kt @@ -17,19 +17,18 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import io.ktor.server.testing.* -import java.util.* -import kotlin.test.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.bank.db.* -import tech.libeufin.common.* +import tech.libeufin.bank.BankAccountCreateWithdrawalResponse +import tech.libeufin.bank.BankWithdrawalOperationPostResponse +import tech.libeufin.bank.BankWithdrawalOperationStatus +import tech.libeufin.bank.WithdrawalStatus +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode +import tech.libeufin.common.json +import tech.libeufin.common.obj +import java.util.* +import kotlin.test.assertEquals class BankIntegrationApiTest { // GET /taler-integration/config diff --git a/bank/src/test/kotlin/ConversionApiTest.kt b/bank/src/test/kotlin/ConversionApiTest.kt index a228705f..89de59d1 100644 --- a/bank/src/test/kotlin/ConversionApiTest.kt +++ b/bank/src/test/kotlin/ConversionApiTest.kt @@ -17,18 +17,12 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import io.ktor.server.testing.* -import java.util.* -import kotlin.test.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* +import tech.libeufin.bank.ConversionResponse +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode +import kotlin.test.assertEquals class ConversionApiTest { // GET /conversion-info/config diff --git a/bank/src/test/kotlin/CoreBankApiTest.kt b/bank/src/test/kotlin/CoreBankApiTest.kt index 0660b892..02d410bf 100644 --- a/bank/src/test/kotlin/CoreBankApiTest.kt +++ b/bank/src/test/kotlin/CoreBankApiTest.kt @@ -17,23 +17,20 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* -import io.ktor.http.content.* -import io.ktor.server.engine.* import io.ktor.server.testing.* -import java.time.Duration -import java.time.Instant -import java.util.* -import kotlin.test.* -import kotlinx.coroutines.* import kotlinx.serialization.json.JsonElement import org.junit.Test import tech.libeufin.bank.* -import tech.libeufin.bank.db.* import tech.libeufin.common.* +import java.time.Duration +import java.time.Instant +import java.util.* +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull class CoreBankConfigTest { // GET /config @@ -592,7 +589,7 @@ class CoreBankAccountsApiTest { client.getA("/accounts/merchant").assertOkJson<AccountData> { obj -> assert(obj.is_public) } - }.assertNoContent(); + }.assertNoContent() client.getA("/accounts/merchant").assertOkJson<AccountData> { obj -> assert(!obj.is_public) } @@ -945,7 +942,7 @@ class CoreBankTransactionsApiTest { assertBalance("exchange", "+KUDOS:0") tx("merchant", "KUDOS:1", "exchange", "") // Bounce common to transaction tx("merchant", "KUDOS:1", "exchange", "Malformed") // Bounce malformed transaction - val reservePub = randEddsaPublicKey(); + val reservePub = randEddsaPublicKey() tx("merchant", "KUDOS:1", "exchange", randIncomingSubject(reservePub)) // Accept incoming tx("merchant", "KUDOS:1", "exchange", randIncomingSubject(reservePub)) // Bounce reserve_pub reuse assertBalance("merchant", "-KUDOS:1") diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt index 97a1b4f5..9b84fcc3 100644 --- a/bank/src/test/kotlin/DatabaseTest.kt +++ b/bank/src/test/kotlin/DatabaseTest.kt @@ -17,20 +17,18 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import org.junit.Test +import tech.libeufin.bank.createAdminAccount +import tech.libeufin.bank.db.AccountDAO.AccountCreationResult +import tech.libeufin.common.oneOrNull import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit import java.util.concurrent.TimeUnit -import kotlin.test.* -import kotlinx.coroutines.* -import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.bank.db.AccountDAO.* -import tech.libeufin.common.* +import kotlin.test.assertEquals +import kotlin.test.assertNull class DatabaseTest { diff --git a/bank/src/test/kotlin/JsonTest.kt b/bank/src/test/kotlin/JsonTest.kt index 3a7e5f21..06bb7498 100644 --- a/bank/src/test/kotlin/JsonTest.kt +++ b/bank/src/test/kotlin/JsonTest.kt @@ -17,15 +17,17 @@ * <http://www.gnu.org/licenses/> */ -import java.time.Duration -import java.time.Instant -import java.time.temporal.ChronoUnit import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* +import tech.libeufin.bank.CreditDebitInfo +import tech.libeufin.bank.RelativeTime +import tech.libeufin.bank.TalerProtocolTimestamp +import tech.libeufin.common.TalerAmount +import java.time.Duration +import java.time.Instant +import java.time.temporal.ChronoUnit @Serializable data class MyJsonType( diff --git a/bank/src/test/kotlin/PaytoTest.kt b/bank/src/test/kotlin/PaytoTest.kt index a5211194..e75b8d9f 100644 --- a/bank/src/test/kotlin/PaytoTest.kt +++ b/bank/src/test/kotlin/PaytoTest.kt @@ -17,18 +17,15 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import io.ktor.server.testing.* -import java.util.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* -import kotlin.test.* +import tech.libeufin.bank.BankAccountTransactionInfo +import tech.libeufin.bank.RegisterAccountResponse +import tech.libeufin.bank.TransactionCreateResponse +import tech.libeufin.common.IbanPayto +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.json +import kotlin.test.assertEquals class PaytoTest { // x-taler-bank diff --git a/bank/src/test/kotlin/RevenueApiTest.kt b/bank/src/test/kotlin/RevenueApiTest.kt index dfa0e69c..2a458cd8 100644 --- a/bank/src/test/kotlin/RevenueApiTest.kt +++ b/bank/src/test/kotlin/RevenueApiTest.kt @@ -17,16 +17,9 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* -import io.ktor.client.request.* -import io.ktor.client.statement.* import io.ktor.http.* -import io.ktor.server.testing.* -import java.util.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* import org.junit.Test -import tech.libeufin.bank.* +import tech.libeufin.bank.RevenueIncomingHistory class RevenueApiTest { // GET /accounts/{USERNAME}/taler-revenue/config diff --git a/bank/src/test/kotlin/SecurityTest.kt b/bank/src/test/kotlin/SecurityTest.kt index 16d2b3f8..b37c665b 100644 --- a/bank/src/test/kotlin/SecurityTest.kt +++ b/bank/src/test/kotlin/SecurityTest.kt @@ -17,22 +17,17 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* import io.ktor.client.request.* -import io.ktor.client.statement.* import io.ktor.http.* -import io.ktor.http.content.* -import io.ktor.server.engine.* -import io.ktor.server.testing.* -import kotlin.test.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* +import kotlinx.serialization.json.Json import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* +import tech.libeufin.common.TalerErrorCode +import tech.libeufin.common.deflate +import tech.libeufin.common.json +import tech.libeufin.common.obj inline fun <reified B> HttpRequestBuilder.jsonDeflate(b: B) { - val json = Json.encodeToString(kotlinx.serialization.serializer<B>(), b); + val json = Json.encodeToString(kotlinx.serialization.serializer<B>(), b) contentType(ContentType.Application.Json) headers.set(HttpHeaders.ContentEncoding, "deflate") setBody(json.toByteArray().inputStream().deflate().readBytes()) diff --git a/bank/src/test/kotlin/StatsTest.kt b/bank/src/test/kotlin/StatsTest.kt index 1aa1979e..edbd26b6 100644 --- a/bank/src/test/kotlin/StatsTest.kt +++ b/bank/src/test/kotlin/StatsTest.kt @@ -18,17 +18,17 @@ */ import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import io.ktor.http.content.* -import io.ktor.server.testing.* -import java.time.* -import java.time.Instant -import java.util.* -import kotlin.test.* import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* +import tech.libeufin.bank.MonitorResponse +import tech.libeufin.bank.MonitorWithConversion +import tech.libeufin.bank.Timeframe +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.executeQueryCheck +import tech.libeufin.common.oneOrNull +import tech.libeufin.common.toDbMicros +import java.time.Instant +import java.time.LocalDateTime +import kotlin.test.assertEquals class StatsTest { @Test @@ -46,7 +46,7 @@ class StatsTest { stmt.setLong(3, amount.value) stmt.setInt(4, amount.frac) stmt.setString(5, "") - stmt.executeQueryCheck(); + stmt.executeQueryCheck() } } diff --git a/bank/src/test/kotlin/WireGatewayApiTest.kt b/bank/src/test/kotlin/WireGatewayApiTest.kt index ba1f3360..676e455b 100644 --- a/bank/src/test/kotlin/WireGatewayApiTest.kt +++ b/bank/src/test/kotlin/WireGatewayApiTest.kt @@ -17,17 +17,13 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.plugins.* -import io.ktor.client.request.* -import io.ktor.client.statement.* import io.ktor.http.* -import io.ktor.server.testing.* -import java.util.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* import org.junit.Test -import tech.libeufin.bank.* -import tech.libeufin.common.* +import tech.libeufin.bank.IncomingHistory +import tech.libeufin.bank.OutgoingHistory +import tech.libeufin.common.TalerErrorCode +import tech.libeufin.common.json +import tech.libeufin.common.obj class WireGatewayApiTest { // GET /accounts/{USERNAME}/taler-wire-gateway/config @@ -47,7 +43,7 @@ class WireGatewayApiTest { "exchange_base_url" to "http://exchange.example.com/" "wtid" to randShortHashCode() "credit_account" to merchantPayto.canonical - }; + } authRoutine(HttpMethod.Post, "/accounts/merchant/taler-wire-gateway/transfer", valid_req) @@ -208,7 +204,7 @@ class WireGatewayApiTest { "amount" to "KUDOS:44" "reserve_pub" to randEddsaPublicKey() "debit_account" to merchantPayto.canonical - }; + } authRoutine(HttpMethod.Post, "/accounts/merchant/taler-wire-gateway/admin/add-incoming", valid_req, requireAdmin = true) diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt index f4d3a4a6..40c8bb59 100644 --- a/bank/src/test/kotlin/helpers.kt +++ b/bank/src/test/kotlin/helpers.kt @@ -17,22 +17,23 @@ * <http://www.gnu.org/licenses/> */ -import io.ktor.client.HttpClient +import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* -import java.io.ByteArrayOutputStream -import java.nio.file.* -import kotlin.test.* -import kotlin.io.path.* -import kotlin.random.Random -import kotlinx.coroutines.* -import kotlinx.serialization.json.* +import kotlinx.coroutines.runBlocking import tech.libeufin.bank.* -import tech.libeufin.bank.db.* -import tech.libeufin.bank.db.AccountDAO.* +import tech.libeufin.bank.db.AccountDAO.AccountCreationResult +import tech.libeufin.bank.db.Database import tech.libeufin.common.* +import java.nio.file.NoSuchFileException +import kotlin.io.path.Path +import kotlin.io.path.deleteExisting +import kotlin.io.path.readText +import kotlin.random.Random +import kotlin.test.assertEquals +import kotlin.test.assertNotNull /* ----- Setup ----- */ @@ -156,7 +157,7 @@ fun bankSetup( } fun dbSetup(lambda: suspend (Database) -> Unit) { - setup() { db, _ -> lambda(db) } + setup { db, _ -> lambda(db) } } /* ----- Common actions ----- */ @@ -174,7 +175,7 @@ suspend fun ApplicationTestBuilder.assertBalance(account: String, amount: String client.get("/accounts/$account") { pwAuth("admin") }.assertOkJson<AccountData> { - val balance = it.balance; + val balance = it.balance val fmt = "${if (balance.credit_debit_indicator == CreditDebitInfo.debit) '-' else '+'}${balance.amount}" assertEquals(amount, fmt, "For $account") } @@ -305,7 +306,7 @@ suspend fun tanCode(info: String): String? { val file = Path("/tmp/tan-$info.txt") val code = file.readText() file.deleteExisting() - return code; + return code } catch (e: Exception) { if (e is NoSuchFileException) return null throw e @@ -391,7 +392,7 @@ fun assertException(msg: String, lambda: () -> Unit) { } } -inline suspend fun <reified B> HttpResponse.assertHistoryIds(size: Int, ids: (B) -> List<Long>): B { +suspend inline fun <reified B> HttpResponse.assertHistoryIds(size: Int, ids: (B) -> List<Long>): B { assertOk() val body = json<B>() val history = ids(body) @@ -418,14 +419,14 @@ inline suspend fun <reified B> HttpResponse.assertHistoryIds(size: Int, ids: (B) /* ----- Body helper ----- */ -inline suspend fun <reified B> HttpResponse.assertOkJson(lambda: (B) -> Unit = {}): B { +suspend inline fun <reified B> HttpResponse.assertOkJson(lambda: (B) -> Unit = {}): B { assertOk() val body = json<B>() lambda(body) return body } -inline suspend fun <reified B> HttpResponse.assertAcceptedJson(lambda: (B) -> Unit = {}): B { +suspend inline fun <reified B> HttpResponse.assertAcceptedJson(lambda: (B) -> Unit = {}): B { assertAccepted() val body = json<B>() lambda(body) @@ -435,7 +436,7 @@ inline suspend fun <reified B> HttpResponse.assertAcceptedJson(lambda: (B) -> Un /* ----- Auth ----- */ /** Auto auth get request */ -inline suspend fun HttpClient.getA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { +suspend inline fun HttpClient.getA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return get(url) { pwAuth() builder(this) @@ -443,7 +444,7 @@ inline suspend fun HttpClient.getA(url: String, builder: HttpRequestBuilder.() - } /** Auto auth post request */ -inline suspend fun HttpClient.postA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { +suspend inline fun HttpClient.postA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return post(url) { pwAuth() builder(this) @@ -451,7 +452,7 @@ inline suspend fun HttpClient.postA(url: String, builder: HttpRequestBuilder.() } /** Auto auth patch request */ -inline suspend fun HttpClient.patchA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { +suspend inline fun HttpClient.patchA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return patch(url) { pwAuth() builder(this) @@ -459,7 +460,7 @@ inline suspend fun HttpClient.patchA(url: String, builder: HttpRequestBuilder.() } /** Auto auth delete request */ -inline suspend fun HttpClient.deleteA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { +suspend inline fun HttpClient.deleteA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return delete(url) { pwAuth() builder(this) @@ -483,7 +484,7 @@ fun HttpRequestBuilder.pwAuth(username: String? = null) { fun randBytes(lenght: Int): ByteArray { val bytes = ByteArray(lenght) - kotlin.random.Random.nextBytes(bytes) + Random.nextBytes(bytes) return bytes } diff --git a/bank/src/test/kotlin/routines.kt b/bank/src/test/kotlin/routines.kt index 6618b157..c0c10c54 100644 --- a/bank/src/test/kotlin/routines.kt +++ b/bank/src/test/kotlin/routines.kt @@ -17,15 +17,20 @@ * <http://www.gnu.org/licenses/> */ -import tech.libeufin.bank.* -import tech.libeufin.common.* -import io.ktor.client.statement.HttpResponse -import io.ktor.server.testing.ApplicationTestBuilder import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* -import kotlin.test.* -import kotlinx.coroutines.* -import kotlinx.serialization.json.* +import io.ktor.server.testing.* +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.serialization.json.JsonObject +import tech.libeufin.bank.BankAccountCreateWithdrawalResponse +import tech.libeufin.bank.WithdrawalStatus +import tech.libeufin.common.TalerAmount +import tech.libeufin.common.TalerErrorCode +import tech.libeufin.common.json +import kotlin.test.assertEquals // Test endpoint is correctly authenticated suspend fun ApplicationTestBuilder.authRoutine( @@ -80,7 +85,7 @@ suspend fun ApplicationTestBuilder.authRoutine( } } -inline suspend fun <reified B> ApplicationTestBuilder.historyRoutine( +suspend inline fun <reified B> ApplicationTestBuilder.historyRoutine( url: String, crossinline ids: (B) -> List<Long>, registered: List<suspend () -> Unit>, @@ -201,7 +206,7 @@ inline suspend fun <reified B> ApplicationTestBuilder.historyRoutine( history("delta=-10&start=${id-4}").assertHistory(10) } -inline suspend fun <reified B> ApplicationTestBuilder.statusRoutine( +suspend inline fun <reified B> ApplicationTestBuilder.statusRoutine( url: String, crossinline status: (B) -> WithdrawalStatus ) { |