diff --git a/modules/joex/src/main/scala/docspell/joex/ConfigFile.scala b/modules/joex/src/main/scala/docspell/joex/ConfigFile.scala index d7f8b175..adcc928c 100644 --- a/modules/joex/src/main/scala/docspell/joex/ConfigFile.scala +++ b/modules/joex/src/main/scala/docspell/joex/ConfigFile.scala @@ -11,6 +11,7 @@ import cats.effect.Async import docspell.config.Implicits._ import docspell.config.{ConfigFactory, FtsType, Validation} import docspell.scheduler.CountingScheme +import docspell.store.Db import emil.MailAddress import emil.javamail.syntax._ @@ -59,7 +60,7 @@ object ConfigFile { cfg.fullTextSearch.enabled && cfg.fullTextSearch.backend == FtsType.PostgreSQL && cfg.fullTextSearch.postgresql.useDefaultConnection && - !cfg.jdbc.dbmsName.contains("postgresql"), + cfg.jdbc.dbms != Db.PostgreSQL, s"PostgreSQL defined fulltext search backend with default-connection, which is not a PostgreSQL connection!" ) ) diff --git a/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala b/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala index a3f6d222..c3cbd825 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/ConfigFile.scala @@ -16,6 +16,7 @@ import docspell.config.Implicits._ import docspell.config.{ConfigFactory, FtsType, Validation} import docspell.oidc.{ProviderConfig, SignatureAlgo} import docspell.restserver.auth.OpenId +import docspell.store.Db import pureconfig._ import pureconfig.generic.auto._ @@ -113,7 +114,7 @@ object ConfigFile { cfg.fullTextSearch.enabled && cfg.fullTextSearch.backend == FtsType.PostgreSQL && cfg.fullTextSearch.postgresql.useDefaultConnection && - !cfg.backend.jdbc.dbmsName.contains("postgresql"), + cfg.backend.jdbc.dbms != Db.PostgreSQL, s"PostgreSQL defined fulltext search backend with default-connection, which is not a PostgreSQL connection!" ) diff --git a/modules/store/src/main/scala/docspell/store/Db.scala b/modules/store/src/main/scala/docspell/store/Db.scala new file mode 100644 index 00000000..5017c115 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/Db.scala @@ -0,0 +1,48 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store + +import cats.data.NonEmptyList + +import io.circe.{Decoder, Encoder} + +sealed trait Db { + def name: String + def driverClass: String +} + +object Db { + + case object PostgreSQL extends Db { + val name = "postgresql" + val driverClass = "org.postgresql.Driver" + } + + case object MariaDB extends Db { + val name = "mariadb" + val driverClass = "org.mariadb.jdbc.Driver" + } + + case object H2 extends Db { + val name = "h2" + val driverClass = "org.h2.Driver" + } + + val all: NonEmptyList[Db] = NonEmptyList.of(PostgreSQL, MariaDB, H2) + + def fromString(str: String): Either[String, Db] = + all.find(_.name.equalsIgnoreCase(str)).toRight(s"Unsupported db name: $str") + + def unsafeFromString(str: String): Db = + fromString(str).fold(sys.error, identity) + + implicit val jsonDecoder: Decoder[Db] = + Decoder.decodeString.emap(fromString) + + implicit val jsonEncoder: Encoder[Db] = + Encoder.encodeString.contramap(_.name) +} diff --git a/modules/store/src/main/scala/docspell/store/JdbcConfig.scala b/modules/store/src/main/scala/docspell/store/JdbcConfig.scala index c0f86478..65fdf3a0 100644 --- a/modules/store/src/main/scala/docspell/store/JdbcConfig.scala +++ b/modules/store/src/main/scala/docspell/store/JdbcConfig.scala @@ -10,35 +10,21 @@ import docspell.common.LenientUri case class JdbcConfig(url: LenientUri, user: String, password: String) { - val dbmsName: Option[String] = - JdbcConfig.extractDbmsName(url) - - def driverClass = - dbmsName match { - case Some("mariadb") => - "org.mariadb.jdbc.Driver" - case Some("postgresql") => - "org.postgresql.Driver" - case Some("h2") => - "org.h2.Driver" - case Some("sqlite") => - "org.sqlite.JDBC" - case Some(n) => - sys.error(s"Unknown DBMS: $n") - case None => - sys.error("No JDBC url specified") - } + val dbms: Db = + JdbcConfig.extractDbmsName(url).fold(sys.error, identity) override def toString: String = s"JdbcConfig(${url.asString}, $user, ***)" } object JdbcConfig { - def extractDbmsName(jdbcUrl: LenientUri): Option[String] = + private def extractDbmsName(jdbcUrl: LenientUri): Either[String, Db] = jdbcUrl.scheme.head match { case "jdbc" => jdbcUrl.scheme.tail.headOption + .map(Db.fromString) + .getOrElse(Left(s"Invalid jdbc url: ${jdbcUrl.asString}")) case _ => - None + Left(s"No scheme provided for url: ${jdbcUrl.asString}") } } diff --git a/modules/store/src/main/scala/docspell/store/Store.scala b/modules/store/src/main/scala/docspell/store/Store.scala index f1c327c0..ffb3000e 100644 --- a/modules/store/src/main/scala/docspell/store/Store.scala +++ b/modules/store/src/main/scala/docspell/store/Store.scala @@ -55,7 +55,7 @@ object Store { ds.setJdbcUrl(jdbc.url.asString) ds.setUsername(jdbc.user) ds.setPassword(jdbc.password) - ds.setDriverClassName(jdbc.driverClass) + ds.setDriverClassName(jdbc.dbms.driverClass) } xa = HikariTransactor(ds, connectEC) fr = FileRepository.apply(xa, ds, fileRepoConfig, true) diff --git a/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala b/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala index e0b1e2d5..1ed56439 100644 --- a/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala +++ b/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala @@ -26,15 +26,7 @@ class FlywayMigrate[F[_]: Sync]( private[this] val logger = docspell.logging.getLogger[F] private def createLocations(folder: String) = - jdbc.dbmsName match { - case Some(dbtype) => - List(s"classpath:db/$folder/$dbtype", s"classpath:db/$folder/common") - case None => - logger.warn( - s"Cannot read database name from jdbc url: ${jdbc.url}. Go with H2" - ) - List(s"classpath:db/$folder/h2", s"classpath:db/$folder/common") - } + List(s"classpath:db/$folder/${jdbc.dbms.name}", s"classpath:db/$folder/common") def createFlyway(kind: MigrationKind): F[Flyway] = for { diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala index cbff6a1f..04583fed 100644 --- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala +++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala @@ -57,29 +57,27 @@ object StoreFixture { def dataSource(jdbc: JdbcConfig): Resource[IO, JdbcConnectionPool] = { def jdbcConnPool = - jdbc.dbmsName match { - case Some("mariadb") => + jdbc.dbms match { + case Db.MariaDB => val ds = new MariaDbDataSource() ds.setUrl(jdbc.url.asString) ds.setUser(jdbc.user) ds.setPassword(jdbc.password) JdbcConnectionPool.create(ds) - case Some("postgresql") => + case Db.PostgreSQL => val ds = new PGConnectionPoolDataSource() ds.setURL(jdbc.url.asString) ds.setUser(jdbc.user) ds.setPassword(jdbc.password) JdbcConnectionPool.create(ds) - case Some("h2") => + case Db.H2 => val ds = new JdbcDataSource() ds.setURL(jdbc.url.asString) ds.setUser(jdbc.user) ds.setPassword(jdbc.password) JdbcConnectionPool.create(ds) - - case n => sys.error(s"Unknown db name: $n") } Resource.make(IO(jdbcConnPool))(cp => IO(cp.dispose()))