libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit cb2d383dc8c4a57f070067848dfdfdc218dd0ad5
parent 25e30f2266920b7a7f2f9605e2fa25c550d6cfe9
Author: MS <ms@taler.net>
Date:   Fri, 22 Sep 2023 14:16:42 +0200

Adding conditional admin account creation.

Diffstat:
Mbank/src/main/kotlin/tech/libeufin/bank/Main.kt | 5+++++
Mbank/src/main/kotlin/tech/libeufin/bank/helpers.kt | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbank/src/test/kotlin/DatabaseTest.kt | 14++++++++++++++
3 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt @@ -47,11 +47,14 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.* import kotlinx.serialization.modules.SerializersModule import net.taler.common.errorcodes.TalerErrorCode +import net.taler.wallet.crypto.Base32Crockford import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level import tech.libeufin.util.* import java.time.Duration +import java.util.Random +import kotlin.system.exitProcess // GLOBALS private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.bank.Main") @@ -292,6 +295,8 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve") val dbConnStr = config.requireValueString("libeufin-bank-db-postgres", "config") logger.info("using database '$dbConnStr'") val db = Database(dbConnStr) + if (!maybeCreateAdminAccount(db)) // logs provided by the helper + exitProcess(1) embeddedServer(Netty, port = 8080) { corebankWebApp(db) }.start(wait = true) diff --git a/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt b/bank/src/main/kotlin/tech/libeufin/bank/helpers.kt @@ -33,6 +33,7 @@ import tech.libeufin.util.* import java.lang.NumberFormatException import java.net.URL import java.util.* +import kotlin.system.exitProcess const val FRACTION_BASE = 100000000 @@ -456,3 +457,68 @@ fun getHistoryParams(req: ApplicationRequest): HistoryParams { } return HistoryParams(delta = delta, start = start) } + +/** + * This function creates the admin account ONLY IF it was + * NOT found in the database. It sets it to a random password that + * is only meant to be overridden by a dedicated CLI tool. + * + * It returns false in case of problems, true otherwise. + */ +fun maybeCreateAdminAccount(db: Database): Boolean { + val maybeAdminCustomer = db.customerGetFromLogin("admin") + val adminCustomerId: Long = if (maybeAdminCustomer == null) { + logger.debug("Creating admin's customer row") + val pwBuf = ByteArray(32) + Random().nextBytes(pwBuf) + val adminCustomer = Customer( + login = "admin", + passwordHash = Base32Crockford.encode(pwBuf), + name = "Bank administrator" + ) + val rowId = db.customerCreate(adminCustomer) + if (rowId == null) { + logger.error("Could not create the admin customer row.") + return false + } + rowId + } + else + maybeAdminCustomer.expectRowId() + val maybeAdminBankAccount = db.bankAccountGetFromOwnerId(adminCustomerId) + if (maybeAdminBankAccount == null) { + logger.debug("Creating admin's bank account row.") + val adminMaxDebt = db.configGet("admin_max_debt") + if (adminMaxDebt == null) { + logger.error("admin_max_debt not found in the config.") + return false + } + val adminMaxDebtObj = parseTalerAmount2(adminMaxDebt, FracDigits.EIGHT) + if (adminMaxDebtObj == null) { + logger.error("admin_max_debt was invalid in the config.") + return false + } + val internalCurrency = db.configGet("internal_currency") + if (internalCurrency == null) { + logger.error("Bank own currency (internal_currency) not found in the config.") + exitProcess(1) + } + if (adminMaxDebtObj.currency != internalCurrency) { + logger.error("admin_max_debt has an unsupported currency: ${adminMaxDebtObj.currency}.") + return false + } + val adminBankAccount = BankAccount( + hasDebt = false, + internalPaytoUri = genIbanPaytoUri(), + owningCustomerId = adminCustomerId, + isPublic = false, + isTalerExchange = false, + maxDebt = adminMaxDebtObj + ) + if (db.bankAccountCreate(adminBankAccount) == null) { + logger.error("Failed at creating admin's bank account row.") + return false + } + } + return true +} diff --git a/bank/src/test/kotlin/DatabaseTest.kt b/bank/src/test/kotlin/DatabaseTest.kt @@ -75,6 +75,20 @@ class DatabaseTest { ) val fooPaysBar = genTx() + // Testing the helper that creates the admin account. + @Test + fun createAdminTest() { + val db = initDb() + val noAdminCustomer = db.customerGetFromLogin("admin") + assert(noAdminCustomer == null) + db.configSet("admin_max_debt", "KUDOS:2222") + assert(maybeCreateAdminAccount(db)) + val yesAdminCustomer = db.customerGetFromLogin("admin") + assert(yesAdminCustomer != null) + assert(db.bankAccountGetFromOwnerId(yesAdminCustomer!!.expectRowId()) != null) + assert(maybeCreateAdminAccount(db)) + } + /** * Tests the SQL function that performs the instructions * given by the exchange to pay one merchant.