libeufin

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

config.kt (3292B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024 Taler Systems S.A.
      4  *
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9  *
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.common.db
     21 
     22 import io.ktor.http.*
     23 import org.postgresql.ds.PGSimpleDataSource
     24 import org.postgresql.jdbc.PgConnection
     25 import java.net.URI
     26 import java.nio.file.Path
     27 
     28 fun currentUser(): String = System.getProperty("user.name")
     29 
     30 /**
     31  * This function converts postgresql:// URIs to JDBC URIs.
     32  *
     33  * URIs that are already jdbc: URIs are passed through.
     34  *
     35  * This avoids the user having to create complex JDBC URIs for postgres connections.
     36  * They are especially complex when using unix domain sockets, as they're not really
     37  * supported natively by JDBC.
     38  */
     39 fun jdbcFromPg(pgConn: String): String {
     40     // Pass through jdbc URIs.
     41     if (pgConn.startsWith("jdbc:")) {
     42         return pgConn
     43     }
     44     require(pgConn.startsWith("postgresql://") || pgConn.startsWith("postgres://")) {
     45         "Not a Postgres connection string: $pgConn"
     46     }
     47     val uri = URI(pgConn)
     48     val params = parseQueryString(uri.query ?: "", decode = false)
     49 
     50     val host = uri.host ?: params["host"] ?: System.getenv("PGHOST")
     51     if (host == null || host.startsWith('/')) {
     52         val port = (if (uri.port == -1) null else uri.port.toString()) ?: params["port"] ?: System.getenv("PGPORT") ?: "5432"
     53         val user = params["user"] ?: currentUser()
     54         val unixPath = (host ?:"/var/run/postgresql") + "/.s.PGSQL.$port"
     55         return "jdbc:postgresql://localhost${uri.path}?user=$user&socketFactory=org.newsclub.net.unix." +
     56                 "AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=$unixPath"
     57     }
     58     if (pgConn.startsWith("postgres://")) {
     59         // The JDBC driver doesn't like postgres://, only postgresql://.
     60         // For consistency with other components, we normalize the postgres:// URI
     61         // into one that the JDBC driver likes.
     62         return "jdbc:postgresql://" + pgConn.removePrefix("postgres://")
     63     }
     64     logger.info("connecting to database via JDBC string '$pgConn'")
     65     return "jdbc:$pgConn"
     66 }
     67 
     68 data class DatabaseConfig(
     69     val dbConnStr: String,
     70     val sqlDir: Path
     71 )
     72 
     73 fun pgDataSource(dbConfig: String): PGSimpleDataSource {
     74     val jdbcConnStr = jdbcFromPg(dbConfig)
     75     logger.debug("connecting to database via JDBC string '$jdbcConnStr'")
     76     val pgSource = PGSimpleDataSource()
     77     pgSource.setUrl(jdbcConnStr)
     78     pgSource.prepareThreshold = 1
     79     return pgSource
     80 }
     81 
     82 fun PGSimpleDataSource.pgConnection(schema: String? = null): PgConnection {
     83     val conn = connection.unwrap(PgConnection::class.java)
     84     if (schema != null) conn.execSQLUpdate("SET search_path TO $schema")
     85     return conn
     86 }