From 0e40aef80a9576fa06763d4239f85930c04768cd Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 10:58:31 +0200 Subject: [PATCH 01/10] First few changes towards scala 3 --- build.sbt | 17 +-- .../scala/sharry/backend/share/Queries.scala | 4 +- .../main/scala/sharry/logging/LazyMap.scala | 2 +- .../main/scala/sharry/logging/LogConfig.scala | 3 +- .../sharry/logging/LoggerExtension.scala | 4 +- .../sharry/logging/impl/JsonWriter.scala | 26 ---- .../sharry/logging/impl/LogfmtWriter.scala | 32 ----- .../scala/sharry/logging/impl/Record.scala | 125 ------------------ .../sharry/logging/impl/ScribeConfigure.scala | 5 +- .../main/scala/sharry/store/AddResult.scala | 4 +- project/Dependencies.scala | 6 +- 11 files changed, 20 insertions(+), 208 deletions(-) delete mode 100644 modules/logging/scribe/src/main/scala/sharry/logging/impl/JsonWriter.scala delete mode 100644 modules/logging/scribe/src/main/scala/sharry/logging/impl/LogfmtWriter.scala delete mode 100644 modules/logging/scribe/src/main/scala/sharry/logging/impl/Record.scala diff --git a/build.sbt b/build.sbt index 135de189..acf0909c 100644 --- a/build.sbt +++ b/build.sbt @@ -13,7 +13,7 @@ val scalafixSettings = Seq( val sharedSettings = Seq( organization := "com.github.eikek", - scalaVersion := "2.13.14", + scalaVersion := "3.3.3", scalacOptions ++= Seq( "-deprecation", "-encoding", @@ -22,12 +22,7 @@ val sharedSettings = Seq( "-feature", "-Werror", // fail when there are warnings "-unchecked", - // remove -byname-implicit, once https://github.com/scala/bug/issues/12072 is resolved - "-Xlint:-byname-implicit,_", - "-Wdead-code", - "-Wunused", - "-Wvalue-discard", - "-Wnumeric-widen" + "-Wvalue-discard" ), Compile / console / scalacOptions := Seq(), Test / console / scalacOptions := Seq() @@ -124,7 +119,7 @@ val loggingApi = project .settings(testSettingsMUnit) .settings( name := "sharry-logging-api", - addCompilerPlugin(Dependencies.kindProjectorPlugin), +// addCompilerPlugin(Dependencies.kindProjectorPlugin), libraryDependencies ++= Dependencies.circeCore ++ Dependencies.fs2 ++ @@ -152,7 +147,7 @@ val loggingScribe = project .settings(testSettingsMUnit) .settings( name := "sharry-logging-scribe", - addCompilerPlugin(Dependencies.kindProjectorPlugin), +// addCompilerPlugin(Dependencies.kindProjectorPlugin), libraryDependencies ++= Dependencies.scribe ++ Dependencies.circeCore ++ @@ -287,8 +282,8 @@ val restserver = project Dependencies.pureconfig ++ Dependencies.yamusca ++ Dependencies.webjars, - addCompilerPlugin(Dependencies.kindProjectorPlugin), - addCompilerPlugin(Dependencies.betterMonadicFor), +// addCompilerPlugin(Dependencies.kindProjectorPlugin), +// addCompilerPlugin(Dependencies.betterMonadicFor), buildInfoPackage := "sharry.restserver", reStart / javaOptions ++= Seq( diff --git a/modules/backend/src/main/scala/sharry/backend/share/Queries.scala b/modules/backend/src/main/scala/sharry/backend/share/Queries.scala index 4d7b29b2..8a1f34c4 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/Queries.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/Queries.scala @@ -2,7 +2,7 @@ package sharry.backend.share import cats.data.OptionT import cats.effect._ -import cats.implicits._ +import cats.syntax.all._ import fs2.Stream import sharry.common._ @@ -384,7 +384,7 @@ object Queries { fids <- allFileIds _ <- store.transact(RShare.delete(share)) _ <- - if (background) Async[F].start(deleteAllFiles(fids)) + if (background) Async[F].start(deleteAllFiles(fids)).void else deleteAllFiles(fids) } yield () } diff --git a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala index f1940018..e40625f4 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala @@ -2,7 +2,7 @@ package sharry.logging import sharry.logging.LazyMap.Val -final class LazyMap[A, B]( +final class LazyMap[A, B] private( private val values: Map[A, Val[B]] ) { lazy val toMap: Map[A, B] = values.view.mapValues(_.value).toMap diff --git a/modules/logging/api/src/main/scala/sharry/logging/LogConfig.scala b/modules/logging/api/src/main/scala/sharry/logging/LogConfig.scala index d1b72ed4..24a50d0c 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LogConfig.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LogConfig.scala @@ -37,10 +37,9 @@ object LogConfig { case object Plain extends Format case object Fancy extends Format case object Json extends Format - case object Logfmt extends Format val all: NonEmptyList[Format] = - NonEmptyList.of(Plain, Fancy, Json, Logfmt) + NonEmptyList.of(Plain, Fancy, Json) def fromString(str: String): Either[String, Format] = all.find(_.name.equalsIgnoreCase(str)).toRight(s"Invalid format name: $str") diff --git a/modules/logging/api/src/main/scala/sharry/logging/LoggerExtension.scala b/modules/logging/api/src/main/scala/sharry/logging/LoggerExtension.scala index 7607ac31..363a036f 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LoggerExtension.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LoggerExtension.scala @@ -11,8 +11,8 @@ import fs2.Stream trait LoggerExtension[F[_]] { self: Logger[F] => - def stream: Logger[Stream[F, *]] = - new Logger[Stream[F, *]] { + def stream: Logger[[X] =>> Stream[F, X]] = + new Logger[[X] =>> Stream[F, X]] { def log(ev: LogEvent) = Stream.eval(self.log(ev)) diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/impl/JsonWriter.scala b/modules/logging/scribe/src/main/scala/sharry/logging/impl/JsonWriter.scala deleted file mode 100644 index b07838f8..00000000 --- a/modules/logging/scribe/src/main/scala/sharry/logging/impl/JsonWriter.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2020 Eike K. & Contributors - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package sharry.logging.impl - -import io.circe.syntax._ -import scribe._ -import scribe.output._ -import scribe.output.format.OutputFormat -import scribe.writer._ - -final case class JsonWriter(writer: Writer, compact: Boolean = true) extends Writer { - override def write( - record: LogRecord, - output: LogOutput, - outputFormat: OutputFormat - ): Unit = { - val r = Record.fromLogRecord(record) - val json = r.asJson - val jsonString = if (compact) json.noSpaces else json.spaces2 - writer.write(record, new TextOutput(jsonString), outputFormat) - } -} diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/impl/LogfmtWriter.scala b/modules/logging/scribe/src/main/scala/sharry/logging/impl/LogfmtWriter.scala deleted file mode 100644 index 4d597f4a..00000000 --- a/modules/logging/scribe/src/main/scala/sharry/logging/impl/LogfmtWriter.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020 Eike K. & Contributors - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package sharry.logging.impl - -import io.circe.syntax._ -import scribe._ -import scribe.output._ -import scribe.output.format.OutputFormat -import scribe.writer._ - -// https://brandur.org/logfmt -final case class LogfmtWriter(writer: Writer) extends Writer { - override def write( - record: LogRecord, - output: LogOutput, - outputFormat: OutputFormat - ): Unit = { - val r = Record.fromLogRecord(record) - val data = r.data - .map { case (k, v) => - s"$k=${v.noSpaces}" - } - .mkString(" ") - val logfmtStr = - s"""level=${r.level.asJson.noSpaces} levelValue=${r.levelValue} message=${r.message.asJson.noSpaces} fileName=${r.fileName.asJson.noSpaces} className=${r.className.asJson.noSpaces} methodName=${r.methodName.asJson.noSpaces} line=${r.line.asJson.noSpaces} column=${r.column.asJson.noSpaces} $data timestamp=${r.timeStamp} date=${r.date} time=${r.time}""" - writer.write(record, new TextOutput(logfmtStr), outputFormat) - } -} diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/impl/Record.scala b/modules/logging/scribe/src/main/scala/sharry/logging/impl/Record.scala deleted file mode 100644 index f83631d0..00000000 --- a/modules/logging/scribe/src/main/scala/sharry/logging/impl/Record.scala +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2020 Eike K. & Contributors - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package sharry.logging.impl - -import sharry.logging.impl.Record._ - -import io.circe.syntax._ -import io.circe.{Encoder, Json} -import perfolation._ -import scribe.LogRecord -import scribe.mdc.MDC -import scribe.message.Message - -// From: https://github.com/outr/scribe/blob/8e99521e1ee1f0c421629764dd96e4eb193d84bd/json/shared/src/main/scala/scribe/json/JsonWriter.scala -// which would introduce jackson and other dependencies. Modified to work with circe. -// Original licensed under MIT. - -private[impl] case class Record( - level: String, - levelValue: Double, - message: String, - additionalMessages: List[String], - fileName: String, - className: String, - methodName: Option[String], - line: Option[Int], - column: Option[Int], - data: Map[String, Json], - traces: List[Trace], - timeStamp: Long, - date: String, - time: String -) - -private[impl] object Record { - - def fromLogRecord(record: LogRecord): Record = { - val l = record.timeStamp - val traces = record.messages.collect { - case message: Message[_] if message.value.isInstanceOf[Throwable] => - throwable2Trace(message.value.asInstanceOf[Throwable]) - } - val (firstMessage, additionalMessages) = record.messages match { - case h :: rest => - (h.logOutput.plainText, rest.map(_.logOutput.plainText)) - case Nil => - ("", Nil) - } - - Record( - level = record.level.name, - levelValue = record.levelValue, - message = firstMessage, - additionalMessages = additionalMessages, - fileName = record.fileName, - className = record.className, - methodName = record.methodName, - line = record.line, - column = record.column, - data = (record.data ++ MDC.map).map { case (key, value) => - value() match { - case value: Json => key -> value - case value: Int => key -> value.asJson - case value: Long => key -> value.asJson - case value: Double => key -> value.asJson - case any => key -> Json.fromString(any.toString) - } - }, - traces = traces, - timeStamp = l, - date = l.t.F, - time = s"${l.t.T}.${l.t.L}${l.t.z}" - ) - } - - private def throwable2Trace(throwable: Throwable): Trace = { - val elements = throwable.getStackTrace.toList.map { e => - TraceElement(e.getClassName, e.getMethodName, e.getLineNumber) - } - Trace( - throwable.getLocalizedMessage, - elements, - Option(throwable.getCause).map(throwable2Trace) - ) - } - - implicit val jsonEncoder: Encoder[Record] = - Encoder.forProduct14( - "level", - "levelValue", - "message", - "additionalMessages", - "fileName", - "className", - "methodName", - "line", - "column", - "data", - "traces", - "timestamp", - "date", - "time" - )(r => Record.unapply(r).get) - - case class Trace(message: String, elements: List[TraceElement], cause: Option[Trace]) - - object Trace { - implicit def jsonEncoder: Encoder[Trace] = - Encoder.forProduct3("message", "elements", "cause")(r => Trace.unapply(r).get) - - implicit def openEncoder: Encoder[Option[Trace]] = - Encoder.instance(opt => opt.map(jsonEncoder.apply).getOrElse(Json.Null)) - } - - case class TraceElement(`class`: String, method: String, line: Int) - - object TraceElement { - implicit val jsonEncoder: Encoder[TraceElement] = - Encoder.forProduct3("class", "method", "line")(r => TraceElement.unapply(r).get) - } -} diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeConfigure.scala b/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeConfigure.scala index 768e51f6..ea34791c 100644 --- a/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeConfigure.scala +++ b/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeConfigure.scala @@ -39,6 +39,7 @@ object ScribeConfigure { format: LogConfig.Format, level: Level ): Unit = { + val writer = scribe.json.ScribeCirceJsonSupport.writer(SystemOutWriter) val mods: List[scribe.Logger => scribe.Logger] = List( _.clearHandlers(), _.withMinimumLevel(ScribeWrapper.convertLevel(level)), @@ -50,9 +51,7 @@ object ScribeConfigure { case Format.Plain => l.withHandler(formatter = Formatter.classic, writer = SystemOutWriter) case Format.Json => - l.withHandler(writer = JsonWriter(SystemOutWriter)) - case Format.Logfmt => - l.withHandler(writer = LogfmtWriter(SystemOutWriter)) + l.withHandler(writer = writer) } } else l, _.replace() diff --git a/modules/store/src/main/scala/sharry/store/AddResult.scala b/modules/store/src/main/scala/sharry/store/AddResult.scala index c54b92b1..cf423094 100644 --- a/modules/store/src/main/scala/sharry/store/AddResult.scala +++ b/modules/store/src/main/scala/sharry/store/AddResult.scala @@ -15,10 +15,10 @@ sealed trait AddResult { object AddResult { def fromUpdateExpectChange(errMsg: String)(e: Either[Throwable, Int]): AddResult = - e.fold(Failure, n => if (n > 0) Success else Failure(new Exception(errMsg))) + e.fold(Failure.apply, n => if (n > 0) Success else Failure(new Exception(errMsg))) def fromEither[B](e: Either[Throwable, B]): AddResult = - e.fold(Failure, _ => Success) + e.fold(Failure.apply, _ => Success) case object Success extends AddResult { def toEither = Right(()) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 56e21265..63631425 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -29,7 +29,9 @@ object Dependencies { val scribe = Seq( "com.outr" %% "scribe" % ScribeVersion, - "com.outr" %% "scribe-slf4j2" % ScribeVersion + "com.outr" %% "scribe-slf4j2" % ScribeVersion, + "com.outr" %% "scribe-cats" % ScribeVersion, + "com.outr" %% "scribe-json-circe" % ScribeVersion ) val sourcecode = Seq( @@ -69,7 +71,7 @@ object Dependencies { // https://github.com/melrief/pureconfig // MPL 2.0 val pureconfig = Seq( - "com.github.pureconfig" %% "pureconfig" % PureConfigVersion + "com.github.pureconfig" %% "pureconfig-core" % PureConfigVersion ) // https://github.com/h2database/h2database From d4e5b5afb1f0ec6c612147fd70def4ee1926dfd8 Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 23:23:22 +0200 Subject: [PATCH 02/10] WIP: converting config to ciris --- build.sbt | 8 +- .../sharry/common/config/Implicits.scala | 68 ------ .../src/main/resources/reference.conf | 18 +- .../scala/sharry/restserver/RestServer.scala | 3 +- .../restserver/config/ConfigDecoders.scala | 86 ++++++++ .../sharry/restserver/config/ConfigFile.scala | 114 +++++----- .../restserver/config/ConfigValues.scala | 197 ++++++++++++++++++ .../sharry/restserver/config/Hocon.scala | 24 +++ .../restserver/webapp/TemplateRoutes.scala | 2 +- project/Dependencies.scala | 9 + 10 files changed, 382 insertions(+), 147 deletions(-) delete mode 100644 modules/common/src/main/scala/sharry/common/config/Implicits.scala create mode 100644 modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala create mode 100644 modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala create mode 100644 modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala diff --git a/build.sbt b/build.sbt index acf0909c..19c21d73 100644 --- a/build.sbt +++ b/build.sbt @@ -136,8 +136,7 @@ val common = project libraryDependencies ++= Dependencies.fs2 ++ Dependencies.fs2io ++ - Dependencies.circe ++ - Dependencies.pureconfig + Dependencies.circe ) val loggingScribe = project @@ -279,11 +278,10 @@ val restserver = project Dependencies.http4s ++ Dependencies.http4sclient ++ Dependencies.circe ++ - Dependencies.pureconfig ++ + Dependencies.typesafeConfig ++ + Dependencies.ciris ++ Dependencies.yamusca ++ Dependencies.webjars, -// addCompilerPlugin(Dependencies.kindProjectorPlugin), -// addCompilerPlugin(Dependencies.betterMonadicFor), buildInfoPackage := "sharry.restserver", reStart / javaOptions ++= Seq( diff --git a/modules/common/src/main/scala/sharry/common/config/Implicits.scala b/modules/common/src/main/scala/sharry/common/config/Implicits.scala deleted file mode 100644 index fbd52d1f..00000000 --- a/modules/common/src/main/scala/sharry/common/config/Implicits.scala +++ /dev/null @@ -1,68 +0,0 @@ -package sharry.common.config - -import java.nio.file.{Path => JPath} - -import scala.reflect.ClassTag - -import fs2.io.file.Path - -import sharry.common._ - -import com.comcast.ip4s.{Host, Port} -import pureconfig._ -import pureconfig.configurable.genericMapReader -import pureconfig.error.{CannotConvert, FailureReason} -import scodec.bits.ByteVector - -trait Implicits { - implicit val pathReader: ConfigReader[Path] = - ConfigReader[JPath].map(Path.fromNioPath) - - implicit val lenientUriReader: ConfigReader[LenientUri] = - ConfigReader[String].emap(reason(LenientUri.parse)) - - implicit val durationReader: ConfigReader[Duration] = - ConfigReader[scala.concurrent.duration.Duration].map(sd => Duration(sd)) - - implicit val passwordReader: ConfigReader[Password] = - ConfigReader[String].map(Password(_)) - - implicit val identReader: ConfigReader[Ident] = - ConfigReader[String].emap(reason(Ident.fromString)) - - implicit def identMapReader[B: ConfigReader]: ConfigReader[Map[Ident, B]] = - genericMapReader[Ident, B](reason(Ident.fromString)) - - implicit val byteVectorReader: ConfigReader[ByteVector] = - ConfigReader[String].emap(reason { str => - if (str.startsWith("hex:")) - ByteVector.fromHex(str.drop(4)).toRight("Invalid hex value.") - else if (str.startsWith("b64:")) - ByteVector.fromBase64(str.drop(4)).toRight("Invalid Base64 string.") - else ByteVector.encodeUtf8(str).left.map(_.getMessage()) - }) - - implicit val byteSizeReader: ConfigReader[ByteSize] = - ConfigReader[String].emap(reason(ByteSize.parse)) - - implicit val signupModeReader: ConfigReader[SignupMode] = - ConfigReader[String].emap(reason(SignupMode.fromString)) - - implicit val portReader: ConfigReader[Port] = - ConfigReader[Int].emap(reason(n => Port.fromInt(n).toRight(s"Invalid port: $n"))) - - implicit val hostReader: ConfigReader[Host] = - ConfigReader[String].emap( - reason(s => Host.fromString(s).toRight(s"Invalid host address: $s")) - ) - - def reason[I, A: ClassTag]( - f: I => Either[String, A] - ): I => Either[FailureReason, A] = - in => - f(in).left.map(str => - CannotConvert(in.toString, implicitly[ClassTag[A]].runtimeClass.toString, str) - ) -} - -object Implicits extends Implicits diff --git a/modules/restserver/src/main/resources/reference.conf b/modules/restserver/src/main/resources/reference.conf index fe83db83..383f044f 100644 --- a/modules/restserver/src/main/resources/reference.conf +++ b/modules/restserver/src/main/resources/reference.conf @@ -11,9 +11,7 @@ sharry.restserver { # Where the server binds to. bind { address = "localhost" - address = ${?SHARRY_BIND_ADDRESS} port = 9090 - port = ${?SHARRY_BIND_PORT} } file-download { @@ -242,10 +240,9 @@ sharry.restserver { # denoting the user name # - user-email-key: the name of the field in the json response # that denotes the users email. - oauth = [ - { + oauth = { + "github" = { enabled = false - id = "github" name = "Github" icon = "fab fa-github" scope = "" @@ -256,9 +253,8 @@ sharry.restserver { client-id = "" client-secret = "" }, - { + "google" = { enabled = false - id = "google" name = "Google" icon = "fab fa-google" scope = "" @@ -269,9 +265,8 @@ sharry.restserver { client-id = "" client-secret = "" }, - { + "aad" = { enabled = false - id = "aad" name = "Azure AD" icon = "fab fa-microsoft" scope = "openid" @@ -283,7 +278,7 @@ sharry.restserver { client-id = "" client-secret = "" } - ] + } # Allows to inspect the request headers for finding already # authorized user name/email. If enabled and during login the @@ -303,11 +298,8 @@ sharry.restserver { # use the PostgreSQL compatibility mode. jdbc { url = "jdbc:h2://"${java.io.tmpdir}"/sharry-demo.db;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE" - url = ${?SHARRY_BACKEND_JDBC_URL} user = "sa" - user = ${?SHARRY_BACKEND_JDBC_USER} password = "" - password = ${?SHARRY_BACKEND_JDBC_PASSWORD} } # How files are stored. diff --git a/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala b/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala index a17a044f..2596940d 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala @@ -23,13 +23,14 @@ import org.http4s.ember.server.EmberServerBuilder import org.http4s.headers.{Location, `Content-Length`, `Content-Type`} import org.http4s.server.Router import org.http4s.server.middleware.{Logger => Http4sLogger} +import scribe.Scribe object RestServer { def stream[F[_]: Async: Files: Network]( cfg: Config, pools: Pools ): Stream[F, Nothing] = { - implicit val logger = sharry.logging.getLogger[F] + implicit val logger: Logger[F] = sharry.logging.getLogger[F] val server = httpApp(cfg, pools).flatMap(httpServer(cfg, _)) Stream diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala new file mode 100644 index 00000000..85aafb3d --- /dev/null +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala @@ -0,0 +1,86 @@ +package sharry.restserver.config + +import cats.syntax.all._ +import com.typesafe.config.{ConfigValue as TCValue} +import org.http4s.Uri +import ciris._ +import com.comcast.ip4s.{Host, Port} +import sharry.common._ +import cats.Show +import sharry.logging.Level +import sharry.logging.LogConfig +import scala.jdk.CollectionConverters._ +import scodec.bits.ByteVector + +private [config] trait ConfigDecoders: + extension [A,B](self: ConfigDecoder[A,B]) + def emap[C](typeName: String)(f: B => Either[String, C])(using Show[B]) = + self.mapEither((key, b) => f(b).left.map(err => ConfigError.decode(typeName, key, b))) + + given ConfigDecoder[TCValue, String] = + ConfigDecoder[TCValue].map(_.atKey("a").getString("a")) + + given ConfigDecoder[TCValue, Double] = + ConfigDecoder[TCValue].map(_.atKey("a").getDouble("a")) + + given ConfigDecoder[TCValue, Long] = + ConfigDecoder[TCValue].map(_.atKey("a").getLong("a")) + + given [A](using ConfigDecoder[TCValue, A]): ConfigDecoder[TCValue, List[A]] = + ConfigDecoder[TCValue].mapEither { (cfgKey, cv) => + val inner = cv.atKey("a").getList("a") + inner.asScala.toList.traverse(e => ConfigDecoder[TCValue, A].decode(cfgKey, e)) + } + + given [K, A](using ConfigDecoder[String, K], ConfigDecoder[TCValue, A]): ConfigDecoder[TCValue, Map[K, A]] = + ConfigDecoder[TCValue].mapEither { (cfgKey, cv) => + val inner = cv.atKey("a").getConfig("a") + inner.root.keySet.asScala.toList.traverse { key => + val value = inner.getObject(key) + ConfigDecoder[String, K].decode(cfgKey, key).flatMap( k => + ConfigDecoder[TCValue, A].decode(cfgKey, value).map(v => k -> v) + ) + }.map(_.toMap) + } + + given [A](using ConfigDecoder[String, A]): ConfigDecoder[TCValue, A] = + ConfigDecoder[TCValue, String].as[A] + + given ConfigDecoder[String, Duration] = + ConfigDecoder[String].as[scala.concurrent.duration.Duration].map(Duration.apply) + + given ConfigDecoder[String, LenientUri] = + ConfigDecoder[String].emap("LenientUri")(LenientUri.parse) + + given ConfigDecoder[String, ByteVector] = + ConfigDecoder[String].emap("ByteVector") { str => + if (str.startsWith("hex:")) + ByteVector.fromHex(str.drop(4)).toRight(s"Invalid hex value: $str") + else if (str.startsWith("b64:")) + ByteVector.fromBase64(str.drop(4)).toRight(s"Invalid Base64 string: $str") + else ByteVector.encodeUtf8(str).left.map(_.getMessage()) + } + + given ConfigDecoder[String, Ident] = + ConfigDecoder[String].emap("Ident")(Ident.fromString) + + given ConfigDecoder[String, Password] = + ConfigDecoder[String].map(Password.apply) + + given ConfigDecoder[String, Uri] = + ConfigDecoder[String].mapOption("Uri")(Uri.fromString(_).toOption) + + given ConfigDecoder[String, Host] = + ConfigDecoder[String].mapOption("Host")(Host.fromString) + + given ConfigDecoder[String, Port] = + ConfigDecoder[String].mapOption("Port")(Port.fromString) + + given ConfigDecoder[String, ByteSize] = + ConfigDecoder[String].emap("ByteSize")(ByteSize.parse) + + given ConfigDecoder[String, Level] = + ConfigDecoder[String].emap("Level")(Level.fromString) + + given ConfigDecoder[String, LogConfig.Format] = + ConfigDecoder[String].emap("LogFormat")(LogConfig.Format.fromString) diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala index 76cb15cd..f7bfdb27 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala @@ -1,66 +1,62 @@ package sharry.restserver.config -import sharry.common.config.Implicits._ -import sharry.logging.{Level, LogConfig} -import sharry.store.{FileStoreConfig, FileStoreType} +//import sharry.logging.{Level, LogConfig} +//import sharry.store.{FileStoreConfig, FileStoreType} -import emil.MailAddress -import emil.SSLType -import emil.javamail.syntax._ -import pureconfig._ -import pureconfig.generic.auto._ -import pureconfig.generic.{CoproductHint, FieldCoproductHint} -import yamusca.imports.{Template, mustache} +// import emil.MailAddress +// import emil.SSLType +// import emil.javamail.syntax._ +// import yamusca.imports.{Template, mustache} object ConfigFile { - import Implicits._ - - def loadConfig: Config = - ConfigSource.default.at("sharry.restserver").loadOrThrow[Config].validOrThrow - - object Implicits { - implicit val mailAddressReader: ConfigReader[Option[MailAddress]] = - ConfigReader[String].emap( - reason(s => - if (s.trim.isEmpty) Right(None) else MailAddress.parse(s).map(m => Some(m)) - ) - ) - - implicit val mailSslTypeReader: ConfigReader[SSLType] = - ConfigReader[String].emap( - reason(s => - s.toLowerCase match { - case "none" => Right(SSLType.NoEncryption) - case "starttls" => Right(SSLType.StartTLS) - case "ssl" => Right(SSLType.SSL) - case _ => Left(s"Invalid ssl type '$s'. Use one of none, ssl or starttls.") - } - ) - ) - - implicit val templateReader: ConfigReader[Template] = - ConfigReader[String].emap( - reason(s => - mustache.parse(s).left.map(err => s"Error parsing template at ${err._1.pos}") - ) - ) - - implicit val logFormatReader: ConfigReader[LogConfig.Format] = - ConfigReader[String].emap(reason(LogConfig.Format.fromString)) - - implicit val logLevelReader: ConfigReader[Level] = - ConfigReader[String].emap(reason(Level.fromString)) - - implicit val fileStoreTypeReader: ConfigReader[FileStoreType] = - ConfigReader[String].emap(reason(FileStoreType.fromString)) - - // the value "s-3" looks strange, this is to allow to write "s3" in the config - implicit val fileStoreCoproductHint: CoproductHint[FileStoreConfig] = - new FieldCoproductHint[FileStoreConfig]("type") { - override def fieldValue(name: String) = - if (name.equalsIgnoreCase("S3")) "s3" - else super.fieldValue(name) - } - } + // import Implicits._ + + def loadConfig: Config = ??? + // ConfigSource.default.at("sharry.restserver").loadOrThrow[Config].validOrThrow + + // object Implicits { + // implicit val mailAddressReader: ConfigReader[Option[MailAddress]] = + // ConfigReader[String].emap( + // reason(s => + // if (s.trim.isEmpty) Right(None) else MailAddress.parse(s).map(m => Some(m)) + // ) + // ) + + // implicit val mailSslTypeReader: ConfigReader[SSLType] = + // ConfigReader[String].emap( + // reason(s => + // s.toLowerCase match { + // case "none" => Right(SSLType.NoEncryption) + // case "starttls" => Right(SSLType.StartTLS) + // case "ssl" => Right(SSLType.SSL) + // case _ => Left(s"Invalid ssl type '$s'. Use one of none, ssl or starttls.") + // } + // ) + // ) + + // implicit val templateReader: ConfigReader[Template] = + // ConfigReader[String].emap( + // reason(s => + // mustache.parse(s).left.map(err => s"Error parsing template at ${err._1.pos}") + // ) + // ) + + // implicit val logFormatReader: ConfigReader[LogConfig.Format] = + // ConfigReader[String].emap(reason(LogConfig.Format.fromString)) + + // implicit val logLevelReader: ConfigReader[Level] = + // ConfigReader[String].emap(reason(Level.fromString)) + + // implicit val fileStoreTypeReader: ConfigReader[FileStoreType] = + // ConfigReader[String].emap(reason(FileStoreType.fromString)) + + // // the value "s-3" looks strange, this is to allow to write "s3" in the config + // implicit val fileStoreCoproductHint: CoproductHint[FileStoreConfig] = + // new FieldCoproductHint[FileStoreConfig]("type") { + // override def fieldValue(name: String) = + // if (name.equalsIgnoreCase("S3")) "s3" + // else super.fieldValue(name) + // } + // } } diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala new file mode 100644 index 00000000..e842fb7c --- /dev/null +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala @@ -0,0 +1,197 @@ +package sharry.restserver.config + +import cats.syntax.all._ +import ciris._ +import org.http4s.Uri +import sharry.restserver.config.Hocon.HoconAt +import com.comcast.ip4s.{Host, Port} +import sharry.common._ +import sharry.logging.Level +import sharry.logging.LogConfig +import sharry.store.JdbcConfig +import scodec.bits.ByteVector +import sharry.backend.auth.AuthConfig +import scala.jdk.CollectionConverters._ +import cats.Applicative + +object ConfigValues extends ConfigDecoders: + private val hocon = Hocon.at("sharry.restserver") + private def senv(envName: String) = env(s"SHARRY_${envName}") + private def key(hoconPath: String, envName: String) = + hocon(hoconPath).as[String].or(senv(envName)) + + private def keyMap[A, B](hoconPath: String, envName: String)(using ConfigDecoder[String, A], ConfigDecoder[String, B]) = + hocon(hoconPath).as[Map[A, B]] + + private def keyList[A](hoconPath: String, envName: String)(using ConfigDecoder[String, A]) = + hocon(hoconPath).as[List[A]] + + val baseUrl = key("base-url", "BASE_URL").as[Uri] + + val bind = { + val address = key("bind.address", "BIND_ADDRESS").as[Host] + val port = key("bind.port", "BIND_PORT").as[Port] + (address, port).mapN(Config.Bind.apply) + } + + val fileDownload = { + val chunkSize = key("file-download.download-chunk-size", + "FILE_DOWNLOAD_CHUNK_SIZE").as[ByteSize] + chunkSize.map(Config.FileDownload.apply) + } + + val logConfig = { + val minLevel = key("logging.minimum-level", "LOGGING_MINIMUM_LEVEL").as[Level] + val fmt = key("logging.format", "LOGGING_FORMAT").as[LogConfig.Format] + val extraLevel = keyMap[String, Level]("logging.levels", "LOGGING_LEVELS") + (minLevel, fmt, extraLevel).mapN(LogConfig.apply) + } + + val aliasMemberEnabled = key("alias-member-enabled", "ALIAS_MEMBER_ENABLED").as[Boolean] + + val webapp = { + val name = key("webapp.app-name", "WEBAPP_NAME") + val icon = key("webapp.app-icon", "WEBAPP_ICON") + val iconDark = key("webapp.app-icon-dark", "WEBAPP_ICON_DARK") + val logo = key("webapp.app-logo", "WEBAPP_LOGO") + val logoDark = key("webapp.app-logo-dark", "WEBAPP_LOGO_DARK") + val footer = key("webapp.app-footer", "WEBAPP_FOOTER") + val footerVisible = key("webapp.app-footer-visible", "WEBAPP_FOOTER_VISIBLE").as[Boolean] + val chunkSize = key("webapp.chunk-size", "WEBAPP_CHUNK_SIZE").as[ByteSize] + val retryDelays= keyList[Duration]("webapp.retry-delays", "WEBAPP_RETRY_DELAYS") + val welcomeMsg = key("webapp.welcome-message", "WEBAPP_WELCOME_MESSAGE") + val defaultLang = key("webapp.default-language", "WEBAPP_DEFAULT_LANGUAGE") + val authRenewal = key("webapp.auth-renewal", "WEBAPP_AUTH_RENEWAL").as[Duration] + val initialPage = key("webapp.initial-page", "WEBAPP_INITIAL_PAGE") + val defaultValidity = key("webapp.default-validity", "WEBAPP_DEFAULT_VALIDITY").as[Duration] + val initialTheme = key("webapp.initial-theme", "WEBAPP_INITIAL_THEME") + val oauthRedirect = key("webapp.oauth-auto-redirect", "WEBAPP_OAUTH_AUTO_REDIRECT").as[Boolean] + val customHead = key("webapp.custom-head", "WEBAPP_CUSTOM_HEAD") + (name, icon, iconDark, logo, logoDark, footer, footerVisible, chunkSize, retryDelays, welcomeMsg, defaultLang, authRenewal, initialPage, defaultValidity, initialTheme, oauthRedirect, customHead).mapN(Config.Webapp.apply) + } + + + val authFixed: ConfigValue[Effect, AuthConfig.Fixed] = { + def k(p: String, e: String) = + key(s"backend.auth.fixed.$p", s"BACKEND_AUTH_FIXED_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val user = k("user", "USER").as[Ident] + val pass = k("password", "PASSWORD").as[Password].redacted + val order = k("order", "ORDER").as[Int] + (enabled, user, pass, order).mapN(AuthConfig.Fixed.apply) + } + + val authHttp = { + def k(p: String, e: String) = + key(s"backend.auth.http.$p", s"BACKEND_AUTH_HTTP_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val url = k("url", "URL").as[LenientUri] + val method = k("method", "METHOD") + val body = k("body", "BODY") + val contentType = k("content-type", "CONTENT_TYPE") + val order = k("order", "ORDER").as[Int] + (enabled, url, method, body, contentType, order).mapN(AuthConfig.Http.apply) + } + + val authHttpBasic = { + def k(p: String, e: String) = + key(s"backend.auth.http-basic.$p", s"BACKEND_AUTH_HTTP_BASIC_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val url = k("url", "URL").as[LenientUri] + val method = k("method", "METHOD") + val order = k("order", "ORDER").as[Int] + (enabled, url, method, order).mapN(AuthConfig.HttpBasic.apply) + } + + val authCommand = { + def k(p: String, e: String) = + key(s"backend.auth.command.$p", s"BACKEND_AUTH_COMMAND_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val program = keyList[String]("backend.auth.command.program", "BACKEND_AUTH_COMMAND_PROGRAM") + val success = k("success", "SUCCESS").as[Int] + val order = k("order", "ORDER").as[Int] + (enabled, program, success, order).mapN(AuthConfig.Command.apply) + } + + val authInternal = { + def k(p: String, e: String) = + key(s"backend.auth.internal.$p", s"BACKEND_AUTH_INTERNAL_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val order = k("order", "ORDER").as[Int] + (enabled, order).mapN(AuthConfig.Internal.apply) + } + + val authProxy = { + def k(p: String, e: String) = + key(s"backend.auth.proxy.$p", s"BACKEND_AUTH_INTERNAL_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val userHeader = k("user-header", "USER_HEADER") + val emailHeader = k("email-header", "EMAIL_HEADER").option + (enabled, userHeader, emailHeader).mapN(AuthConfig.Proxy.apply) + } + + def authOAuth(id: Ident) = { + def k(p: String, e: String) = + key(s"backend.auth.oauth.${id.id}.$p", s"BACKEND_AUTH_OAUTH_${id.id.toUpperCase()}_$e") + val idkey = ConfigKey(s"oauth id key: ${id.id}") + val enabled = k("enabled", "ENABLED").as[Boolean] + val name = k("name", "NAME") + val icon = k("icon", "ICON").option + val scope = k("scope", "SCOPE") + val authorizeUrl = k("authorize-url", "AUTHORIZE_URL").as[LenientUri] + val tokenUrl = k("token-url", "TOKEN_URL").as[LenientUri] + val userUrl = k("user-url", "USER_URL").as[LenientUri] + val userIdkey = k("user-id-key", "USER_ID_KEY") + val userEmailKey = k("user-email-key", "USER_EMAIL_KEY").option + val clientId = k("client-id", "CLIENT_ID") + val clientSecret = k("client-secret", "CLIENT_SECRET") + (ConfigValue.loaded(idkey, id), enabled, name, authorizeUrl, tokenUrl, userUrl, userIdkey, userEmailKey, scope, clientId, clientSecret, icon).mapN(AuthConfig.OAuth.apply) + } + + val authOAuthKeys = { + def stringsToIds(strs: List[String]) = + strs.traverse(Ident.fromString) match + case Right(ids) => ConfigValue.loaded(ConfigKey(""), ids) + case Left(err) => ConfigValue.failed(ConfigError(err)) + + val hoconKeys = + hocon("backend.auth.oauth") + .map(_.atKey("a").getConfig("a").root.keySet.asScala.toList) + .flatMap(stringsToIds) + + val envKeys = + senv("BACKEND_AUTH_OAUTH_IDS").map(s => s.split(',').toList.map(_.trim)) + .flatMap(stringsToIds) + + hoconKeys.or(envKeys) + } + + val authOAuthSeq = + authOAuthKeys.flatMap(ids => + ids.foldLeft(ConfigValue.loaded(ConfigKey(""), List.empty[AuthConfig.OAuth])) { + (cv, id) => cv.flatMap(l => authOAuth(id).map(_ :: l)) + }) + + val auth = { + def k(p: String, e: String) = + key(s"backend.auth.$p", s"BACKEND_AUTH_$e") + val serverSecret = k("server-secret", "SERVER_SECRET").as[ByteVector] + val sessionValid = k("session-valid", "SESSION_VALID").as[Duration] + (serverSecret, sessionValid, authFixed, authHttp, authHttpBasic, authCommand, authProxy, authInternal, authOAuthSeq).mapN(AuthConfig.apply) + } + + val jdbc = { + val url = key("backend.jdbc.url", "BACKEND_JDBC_URL").as[LenientUri] + val user = key("backend.jdbc.user", "BACKEND_JDBC_USER") + val pass = key("backend.jdbc.password", "BACKEND_JDBC_PASSWORD").redacted + (url, user, pass).mapN(JdbcConfig.apply) + } + + +end ConfigValues diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala b/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala new file mode 100644 index 00000000..b25a1227 --- /dev/null +++ b/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala @@ -0,0 +1,24 @@ +package sharry.restserver.config + +import com.typesafe.config.{Config, ConfigValue as TCValue} +import ciris._ +import com.typesafe.config.ConfigException +import com.typesafe.config.ConfigFactory + +private[config] object Hocon: + final class HoconAt(config: Config, path: String): + def apply(name: String): ConfigValue[Effect, TCValue] = + val key = s"$path.$name" + val ckey = ConfigKey(key) + try + val value = config.getValue(key) + ConfigValue.loaded(ckey, value) + catch + case _: ConfigException.Missing => ConfigValue.missing(ckey) + case ex => ConfigValue.failed(ConfigError(ex.getMessage)) + + def at(config: Config)(path: String): HoconAt = + HoconAt(config.resolve(), path) + + def at(path: String): HoconAt = + at(ConfigFactory.load())(path) diff --git a/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala index 39a78839..633471f2 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala @@ -36,7 +36,7 @@ object TemplateRoutes { } def apply[F[_]: Async: Files](cfg: Config): InnerRoutes[F] = { - implicit val logger = sharry.logging.getLogger[F] + implicit val logger: Logger[F] = sharry.logging.getLogger[F] val indexTemplate = memo( loadResource("/index.html").flatMap(loadTemplate(_)) ) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 63631425..3b4f7692 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,6 +6,7 @@ object Dependencies { val BetterMonadicForVersion = "0.3.1" val BinnyVersion = "0.11.0" val CirceVersion = "0.14.7" + val CirisVersion = "3.6.0" val ClipboardJsVersion = "2.0.11" val DoobieVersion = "1.0.0-RC5" val EmilVersion = "0.17.0" @@ -25,8 +26,16 @@ object Dependencies { val SwaggerVersion = "5.17.14" val TikaVersion = "2.9.2" val TusClientVersion = "1.8.0-1" + val TypesafeConfigVersion = "1.4.3" val YamuscaVersion = "0.10.0" + val ciris = Seq( + "is.cir" %% "ciris" % CirisVersion + ) + val typesafeConfig = Seq( + "com.typesafe" % "config" % TypesafeConfigVersion + ) + val scribe = Seq( "com.outr" %% "scribe" % ScribeVersion, "com.outr" %% "scribe-slf4j2" % ScribeVersion, From f5e0f67869c18b10ae3cdc4e96188f1753076b01 Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 23:30:06 +0200 Subject: [PATCH 03/10] scalafmt/scalafix update --- .scalafix.conf | 2 +- .scalafmt.conf | 2 +- .../src/test/scala/sharry/backend/mail/QueriesTest.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.scalafix.conf b/.scalafix.conf index 6f2dc788..da1f0418 100644 --- a/.scalafix.conf +++ b/.scalafix.conf @@ -1,5 +1,4 @@ rules = [ - ProcedureSyntax OrganizeImports ] OrganizeImports { @@ -10,4 +9,5 @@ OrganizeImports { groups = ["re:javax?\\.", "scala.", "re:(cats|fs2)\\.", "sharry.", "*"] importSelectorsOrder = Ascii removeUnused = true + targetDialect = Scala3 } \ No newline at end of file diff --git a/.scalafmt.conf b/.scalafmt.conf index 893865bc..7aec7c06 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,7 +1,7 @@ version = "3.8.1" preset = default -runner.dialect = scala213source3 +runner.dialect = scala3 align.preset = some maxColumn = 90 diff --git a/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala b/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala index 390976aa..70004b16 100644 --- a/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala +++ b/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala @@ -30,7 +30,7 @@ class QueriesTest extends FunSuite with StoreFixture { for { _ <- store.transact(RAccount.insert(account, "warn")) e <- store.transact(Queries.getEmail(accountId)) - _ <- IO(assertEquals(e, Some(MailAddress(Some("jdoe"), "test@test.com")))) + _ <- IO(assertEquals(e, Some(MailAddress.unsafe(Some("jdoe"), "test@test.com")))) } yield () } } From 911ea6a8ddce9370850e9f4ea56076a82d2df940 Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 23:36:02 +0200 Subject: [PATCH 04/10] syntax fix: move private[this] to private --- .../src/main/scala/sharry/backend/account/OAccount.scala | 2 +- .../backend/src/main/scala/sharry/backend/alias/OAlias.scala | 2 +- .../src/main/scala/sharry/backend/auth/CommandAuth.scala | 4 ++-- .../src/main/scala/sharry/backend/auth/FixedAuth.scala | 2 +- .../backend/src/main/scala/sharry/backend/auth/HttpAuth.scala | 2 +- .../src/main/scala/sharry/backend/auth/HttpBasicAuth.scala | 2 +- .../src/main/scala/sharry/backend/auth/InternalAuth.scala | 2 +- .../backend/src/main/scala/sharry/backend/auth/Login.scala | 2 +- .../backend/src/main/scala/sharry/backend/files/OFiles.scala | 2 +- .../backend/src/main/scala/sharry/backend/mail/OMail.scala | 2 +- .../backend/src/main/scala/sharry/backend/share/OShare.scala | 2 +- .../src/main/scala/sharry/backend/signup/OSignup.scala | 2 +- modules/common/src/main/scala/sharry/common/LenientUri.scala | 2 +- .../logging/api/src/main/scala/sharry/logging/LazyMap.scala | 2 +- .../src/main/scala/sharry/logging/impl/ScribeWrapper.scala | 4 ++-- .../restserver/src/main/scala/sharry/restserver/Main.scala | 2 +- .../store/src/main/scala/sharry/store/ComputeChecksum.scala | 2 +- .../src/main/scala/sharry/store/migrate/FlywayMigrate.scala | 2 +- modules/store/src/test/scala/sharry/store/StoreFixture.scala | 2 +- 19 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala b/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala index 354bf218..9a106200 100644 --- a/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala +++ b/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala @@ -45,7 +45,7 @@ object OAccount { def apply[F[_]: Async](store: Store[F]): Resource[F, OAccount[F]] = Resource.pure[F, OAccount[F]](new OAccount[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def changePassword(id: Ident, oldPw: Password, newPw: Password): F[AddResult] = { val update = diff --git a/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala b/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala index aaa92ba1..79039370 100644 --- a/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala +++ b/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala @@ -40,7 +40,7 @@ object OAlias { def apply[F[_]: Async](store: Store[F]): Resource[F, OAlias[F]] = Resource.pure[F, OAlias[F]](new OAlias[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def create(detail: AliasInput): F[AddResult] = store.add( diff --git a/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala index 7cd19588..67c980f5 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala @@ -16,7 +16,7 @@ final class CommandAuth[F[_]: Async]( ops: AddAccount.AccountOps[F], runner: CommandAuth.RunCommand[F] ) { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def login: LoginModule[F] = LoginModule.whenEnabled(cfg.command.enabled)( @@ -69,7 +69,7 @@ object CommandAuth { def systemProcess[F[_]: Sync]: RunCommand[F] = new RunCommand[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def exec(up: UserPassData, cfg: AuthConfig.Command): F[Boolean] = Sync[F].delay { diff --git a/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala index e161c195..5d994524 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala @@ -17,7 +17,7 @@ import sharry.common._ */ final class FixedAuth[F[_]: Async](cfg: AuthConfig, op: OAccount[F]) { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def login: LoginModule[F] = LoginModule { up => diff --git a/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala index 368680bd..50e66077 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala @@ -17,7 +17,7 @@ final class HttpAuth[F[_]: Async]( runner: HttpAuth.RunRequest[F] ) { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def login: LoginModule[F] = LoginModule.whenEnabled(cfg.http.enabled)( diff --git a/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala index 9c8e2376..c462f8d1 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala @@ -15,7 +15,7 @@ final class HttpBasicAuth[F[_]: Async]( runner: HttpBasicAuth.RunRequest[F] ) { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def login: LoginModule[F] = LoginModule.whenEnabled(cfg.httpBasic.enabled)( diff --git a/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala index 6757ff1b..a8d3127f 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala @@ -11,7 +11,7 @@ import sharry.store.records.RAccount final class InternalAuth[F[_]: Async](cfg: AuthConfig, op: OAccount[F]) { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def login: LoginModule[F] = LoginModule.enabledState(cfg.internal.enabled, op, AccountSource.intern)( diff --git a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala index 647fb7c1..3945c3b5 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala @@ -21,7 +21,7 @@ object Login { def apply[F[_]: Async](oacc: OAccount[F]): Resource[F, Login[F]] = Resource.pure[F, Login[F]](new Login[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def loginSession(config: AuthConfig)(sessionKey: String): F[LoginResult] = AuthToken.fromString(sessionKey) match { diff --git a/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala b/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala index c087b8ad..c80a2e64 100644 --- a/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala +++ b/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala @@ -26,7 +26,7 @@ object OFiles { fileConfig: FilesConfig ): OFiles[F] = new OFiles[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def computeBackgroundChecksum: Resource[F, F[Outcome[F, Throwable, Unit]]] = Async[F].background( diff --git a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala index ae69a63f..16b41c03 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala @@ -44,7 +44,7 @@ object OMail { emil: Emil[F] ): Resource[F, OMail[F]] = Resource.pure[F, OMail[F]](new OMail[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def notifyAliasUpload( aliasId: Ident, shareId: Ident, diff --git a/modules/backend/src/main/scala/sharry/backend/share/OShare.scala b/modules/backend/src/main/scala/sharry/backend/share/OShare.scala index fb115628..e8a4cb3d 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/OShare.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/OShare.scala @@ -144,7 +144,7 @@ object OShare { cfg: ShareConfig ): Resource[F, OShare[F]] = Resource.pure[F, OShare[F]](new OShare[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def create(data: ShareData[F], accId: AccountId): F[UploadResult[Ident]] = { val createShare = for { diff --git a/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala b/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala index 5b94007e..13a50e9e 100644 --- a/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala +++ b/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala @@ -23,7 +23,7 @@ object OSignup { def apply[F[_]: Async](store: Store[F]): Resource[F, OSignup[F]] = Resource.pure[F, OSignup[F]](new OSignup[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def newInvite(cfg: SignupConfig)(password: Password): F[NewInviteResult] = if (cfg.mode != SignupMode.Invite) diff --git a/modules/common/src/main/scala/sharry/common/LenientUri.scala b/modules/common/src/main/scala/sharry/common/LenientUri.scala index 51697d70..28bc2fd4 100644 --- a/modules/common/src/main/scala/sharry/common/LenientUri.scala +++ b/modules/common/src/main/scala/sharry/common/LenientUri.scala @@ -232,7 +232,7 @@ object LenientUri { } } - private[this] val delims: Set[Char] = ",/?:@&$# %".toSet + private val delims: Set[Char] = ",/?:@&$# %".toSet private def percent(s: String): String = "%" + ByteVector.encodeUtf8(s).fold(throw _, identity).toHex diff --git a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala index e40625f4..a0a80614 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala @@ -24,7 +24,7 @@ final class LazyMap[A, B] private( } object LazyMap { - private[this] val emptyMap = new LazyMap[Any, Any](Map.empty) + private val emptyMap = new LazyMap[Any, Any](Map.empty) def empty[A, B]: LazyMap[A, B] = emptyMap.asInstanceOf[LazyMap[A, B]] diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeWrapper.scala b/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeWrapper.scala index a4b69677..73077cdb 100644 --- a/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeWrapper.scala +++ b/modules/logging/scribe/src/main/scala/sharry/logging/impl/ScribeWrapper.scala @@ -39,10 +39,10 @@ private[logging] object ScribeWrapper { case Level.Trace => scribe.Level.Trace } - private[this] def emptyMDC: MDC = + private def emptyMDC: MDC = new MDCMap(None) - private[this] def convert(ev: LogEvent) = { + private def convert(ev: LogEvent) = { val level = convertLevel(ev.level) val additional: List[LoggableMessage] = ev.additional .map { diff --git a/modules/restserver/src/main/scala/sharry/restserver/Main.scala b/modules/restserver/src/main/scala/sharry/restserver/Main.scala index d551136c..d013ffe1 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/Main.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/Main.scala @@ -10,7 +10,7 @@ import sharry.logging.impl.ScribeConfigure import sharry.restserver.config.ConfigFile object Main extends IOApp { - private[this] val logger = sharry.logging.getLogger[IO] + private val logger = sharry.logging.getLogger[IO] val connectEC = ThreadFactories.fixed[IO](5, ThreadFactories.ofName("sharry-dbconnect")) diff --git a/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala b/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala index 05cbb9b1..27ccf86d 100644 --- a/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala +++ b/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala @@ -27,7 +27,7 @@ object ComputeChecksum { for { queue <- Queue.bounded[F, Entry](config.capacity) } yield new ComputeChecksum[F] { - private[this] val logger = sharry.logging.getLogger[F] + private val logger = sharry.logging.getLogger[F] def submit(id: BinaryId, hint: Hint): F[Unit] = if (config.enable) queue.offer(Entry(id, hint)) diff --git a/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala b/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala index c35fd586..bab767bf 100644 --- a/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala +++ b/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala @@ -8,7 +8,7 @@ import org.flywaydb.core.Flyway import org.flywaydb.core.api.output.MigrateResult object FlywayMigrate { - private[this] val logger = sharry.logging.unsafeLogger("FlywayMigrate") + private val logger = sharry.logging.unsafeLogger("FlywayMigrate") def run[F[_]: Sync](jdbc: JdbcConfig): F[MigrateResult] = Sync[F].delay { diff --git a/modules/store/src/test/scala/sharry/store/StoreFixture.scala b/modules/store/src/test/scala/sharry/store/StoreFixture.scala index f0b8d2ea..ec2698de 100644 --- a/modules/store/src/test/scala/sharry/store/StoreFixture.scala +++ b/modules/store/src/test/scala/sharry/store/StoreFixture.scala @@ -22,7 +22,7 @@ trait StoreFixture { } object StoreFixture { - private[this] val logger = sharry.logging.unsafeLogger("StoreFixture") + private val logger = sharry.logging.unsafeLogger("StoreFixture") def makeStore[F[_]: Async: Files]: Resource[F, Store[F]] = { def dataSource(jdbc: JdbcConfig): Resource[F, JdbcConnectionPool] = { From 44238c07a6c4763bffc92299ccc9ed4a3fc1c87b Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 23:39:50 +0200 Subject: [PATCH 05/10] update scala to 3.4.2 + syntax changes --- build.sbt | 2 +- .../backend/src/main/scala/sharry/backend/auth/Login.scala | 2 +- .../backend/src/main/scala/sharry/backend/mail/OMail.scala | 2 +- .../scribe/src/main/scala/sharry/logging/package.scala | 2 +- .../src/main/scala/sharry/restserver/oauth/CodeFlow.scala | 4 ++-- modules/store/src/main/scala/sharry/store/FileStore.scala | 2 +- .../src/main/scala/sharry/store/migrate/FlywayMigrate.scala | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 19c21d73..cff6a53d 100644 --- a/build.sbt +++ b/build.sbt @@ -13,7 +13,7 @@ val scalafixSettings = Seq( val sharedSettings = Seq( organization := "com.github.eikek", - scalaVersion := "3.3.3", + scalaVersion := "3.4.2", scalacOptions ++= Seq( "-deprecation", "-encoding", diff --git a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala index 3945c3b5..8ea92a3f 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala @@ -65,7 +65,7 @@ object Login { CommandAuth[F](cfg, ops, CommandAuth.RunCommand.systemProcess[F]).withPosition ).sortBy(_._1).map(_._2) - LoginModule.combine[F](modules: _*) + LoginModule.combine[F](modules*) } } diff --git a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala index 16b41c03..16833c79 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala @@ -90,7 +90,7 @@ object OMail { ) ) } - res <- OptionT.liftF(templates.traverse((send _).tupled)) + res <- OptionT.liftF(templates.traverse((send).tupled)) failedReceiver = res .filter(_.isError) .flatMap(_.receiver) diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/package.scala b/modules/logging/scribe/src/main/scala/sharry/logging/package.scala index 14e23d66..dfe729b8 100644 --- a/modules/logging/scribe/src/main/scala/sharry/logging/package.scala +++ b/modules/logging/scribe/src/main/scala/sharry/logging/package.scala @@ -27,7 +27,7 @@ package object logging { def getLogger[F[_]: Sync](name: String): Logger[F] = new ScribeWrapper.Impl[F](scribe.Logger(name)) - def getLogger[F[_]: Sync](clazz: Class[_]): Logger[F] = + def getLogger[F[_]: Sync](clazz: Class[?]): Logger[F] = new ScribeWrapper.Impl[F](scribe.Logger(clazz.getName)) } diff --git a/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala b/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala index 60ed3c55..f6a3bdc9 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala @@ -131,13 +131,13 @@ object CodeFlow { logHeaders = true, logBody = true, logAction = Some((msg: String) => logger.trace(msg)) - ) _ + ) val lres = ResponseLogger( logHeaders = true, logBody = true, logAction = Some((msg: String) => logger.trace(msg)) - ) _ + ) lreq.andThen(lres)(c) } diff --git a/modules/store/src/main/scala/sharry/store/FileStore.scala b/modules/store/src/main/scala/sharry/store/FileStore.scala index 95cfb6bc..4fa44920 100644 --- a/modules/store/src/main/scala/sharry/store/FileStore.scala +++ b/modules/store/src/main/scala/sharry/store/FileStore.scala @@ -47,7 +47,7 @@ object FileStore { computeChecksumConfig: ComputeChecksumConfig, config: FileStoreConfig ): F[FileStore[F]] = { - val create = FileStoreConfig.createBinaryStore[F](ds, chunkSize) _ + val create = FileStoreConfig.createBinaryStore[F](ds, chunkSize) val as = AttributeStore(xa) for { bs <- create(config) diff --git a/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala b/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala index bab767bf..99e73afd 100644 --- a/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala +++ b/modules/store/src/main/scala/sharry/store/migrate/FlywayMigrate.scala @@ -25,7 +25,7 @@ object FlywayMigrate { .configure() .cleanDisabled(true) .dataSource(jdbc.url.asString, jdbc.user, jdbc.password) - .locations(locations: _*) + .locations(locations*) .baselineOnMigrate(true) .baselineVersion("0") .load() @@ -37,7 +37,7 @@ object FlywayMigrate { .configure() .dataSource(jdbc.url.asString, jdbc.user, jdbc.password) .baselineOnMigrate(true) - .locations(locations: _*) + .locations(locations*) .load() } From 4d8f60d733a56f246cc83eb7e399bcae2a94126e Mon Sep 17 00:00:00 2001 From: eikek Date: Sun, 9 Jun 2024 23:46:23 +0200 Subject: [PATCH 06/10] Reformat code to scala 3 --- build.sbt | 3 + .../scala/sharry/backend/BackendApp.scala | 4 +- .../sharry/backend/account/NewAccount.scala | 4 +- .../sharry/backend/account/OAccount.scala | 12 +- .../sharry/backend/account/Queries.scala | 12 +- .../scala/sharry/backend/alias/OAlias.scala | 8 +- .../sharry/backend/auth/AddAccount.scala | 6 +- .../sharry/backend/auth/AuthConfig.scala | 2 +- .../scala/sharry/backend/auth/AuthToken.scala | 6 +- .../sharry/backend/auth/CommandAuth.scala | 12 +- .../scala/sharry/backend/auth/FixedAuth.scala | 8 +- .../scala/sharry/backend/auth/HttpAuth.scala | 10 +- .../sharry/backend/auth/HttpBasicAuth.scala | 8 +- .../sharry/backend/auth/InternalAuth.scala | 6 +- .../scala/sharry/backend/auth/Login.scala | 4 +- .../sharry/backend/auth/LoginModule.scala | 4 +- .../sharry/backend/auth/UserPassData.scala | 8 +- .../scala/sharry/backend/config/Config.scala | 2 +- .../sharry/backend/config/FilesConfig.scala | 2 +- .../scala/sharry/backend/files/OFiles.scala | 4 +- .../sharry/backend/job/CleanupConfig.scala | 2 +- .../sharry/backend/job/PeriodicCleanup.scala | 8 +- .../sharry/backend/mail/MailConfig.scala | 6 +- .../sharry/backend/mail/NotifyData.scala | 2 +- .../scala/sharry/backend/mail/OMail.scala | 16 +-- .../scala/sharry/backend/mail/Queries.scala | 12 +- .../sharry/backend/mail/TemplateData.scala | 10 +- .../backend/mustache/YamuscaCommon.scala | 4 +- .../sharry/backend/share/ByteResult.scala | 2 +- .../backend/share/DescriptionTemplate.scala | 8 +- .../scala/sharry/backend/share/FileData.scala | 2 +- .../scala/sharry/backend/share/OShare.scala | 8 +- .../scala/sharry/backend/share/Queries.scala | 16 +-- .../sharry/backend/share/ShareConfig.scala | 2 +- .../sharry/backend/share/ShareData.scala | 2 +- .../sharry/backend/share/ShareDetail.scala | 2 +- .../scala/sharry/backend/share/ShareId.scala | 2 +- .../sharry/backend/share/ShareItem.scala | 2 +- .../sharry/backend/share/ShareResult.scala | 2 +- .../sharry/backend/share/UploadResult.scala | 4 +- .../scala/sharry/backend/signup/OSignup.scala | 8 +- .../sharry/backend/signup/SignupConfig.scala | 2 +- .../sharry/backend/auth/LoginModuleTest.scala | 10 +- .../sharry/backend/mail/QueriesTest.scala | 8 +- .../main/scala/sharry/common/AccountId.scala | 2 +- .../scala/sharry/common/AccountState.scala | 2 +- .../scala/sharry/common/BaseJsonCodecs.scala | 2 +- .../main/scala/sharry/common/Duration.scala | 6 +- .../main/scala/sharry/common/EnvMode.scala | 2 +- .../main/scala/sharry/common/LenientUri.scala | 4 +- .../main/scala/sharry/common/SignupMode.scala | 2 +- .../scala/sharry/common/ThreadFactories.scala | 4 +- .../sharry/common/syntax/StreamSyntax.scala | 6 +- .../sharry/common/syntax/StringSyntax.scala | 4 +- .../scala/sharry/common/util/Random.scala | 2 +- .../scala/sharry/logging/AndThenLogger.scala | 2 +- .../main/scala/sharry/logging/LazyMap.scala | 2 +- .../main/scala/sharry/logging/LogEvent.scala | 2 +- .../main/scala/sharry/logging/Logger.scala | 8 +- .../main/scala/sharry/logging/package.scala | 2 +- .../docspell/logging/TestLoggingConfig.scala | 2 +- .../scala/sharry/restserver/CookieData.scala | 6 +- .../main/scala/sharry/restserver/Main.scala | 4 +- .../scala/sharry/restserver/RestAppImpl.scala | 4 +- .../scala/sharry/restserver/RestServer.scala | 13 +- .../sharry/restserver/config/Config.scala | 6 +- .../restserver/config/ConfigDecoders.scala | 46 ++++--- .../restserver/config/ConfigValues.scala | 115 +++++++++++++----- .../sharry/restserver/config/Hocon.scala | 6 +- .../restserver/http4s/ClientRequestInfo.scala | 8 +- .../restserver/http4s/EnvMiddleware.scala | 4 +- .../restserver/http4s/NoCacheMiddleware.scala | 6 +- .../sharry/restserver/oauth/CodeFlow.scala | 10 +- .../sharry/restserver/oauth/StateParam.scala | 4 +- .../restserver/routes/AccountRoutes.scala | 12 +- .../restserver/routes/AliasMemberRoutes.scala | 8 +- .../restserver/routes/AliasRoutes.scala | 12 +- .../restserver/routes/Authenticate.scala | 16 +-- .../restserver/routes/ByteResponse.scala | 10 +- .../scala/sharry/restserver/routes/Conv.scala | 2 +- .../sharry/restserver/routes/InfoRoutes.scala | 6 +- .../restserver/routes/LoginRoutes.scala | 18 +-- .../sharry/restserver/routes/MailRoutes.scala | 12 +- .../restserver/routes/NotifyRoutes.scala | 8 +- .../restserver/routes/OpenShareRoutes.scala | 8 +- .../restserver/routes/RegisterRoutes.scala | 10 +- .../restserver/routes/SettingRoutes.scala | 10 +- .../routes/ShareDetailResponse.scala | 16 +-- .../restserver/routes/ShareRoutes.scala | 16 +-- .../restserver/routes/ShareUploadRoutes.scala | 14 +-- .../routes/tus/SharryFileLength.scala | 2 +- .../restserver/routes/tus/TusRoutes.scala | 10 +- .../restserver/webapp/TemplateRoutes.scala | 20 +-- .../restserver/webapp/WebjarRoutes.scala | 4 +- .../restserver/webapp/YamuscaConverter.scala | 6 +- .../restserver/oauth/StateParamTest.scala | 4 +- .../main/scala/sharry/store/AddResult.scala | 2 +- .../scala/sharry/store/ComputeChecksum.scala | 6 +- .../main/scala/sharry/store/FileStore.scala | 10 +- .../scala/sharry/store/FileStoreConfig.scala | 2 +- .../src/main/scala/sharry/store/Store.scala | 6 +- .../sharry/store/doobie/AttributeStore.scala | 12 +- .../scala/sharry/store/doobie/Column.scala | 4 +- .../sharry/store/doobie/DoobieMeta.scala | 8 +- .../main/scala/sharry/store/doobie/Sql.scala | 4 +- .../scala/sharry/store/doobie/StoreImpl.scala | 10 +- .../sharry/store/records/ModAccount.scala | 2 +- .../scala/sharry/store/records/RAccount.scala | 12 +- .../scala/sharry/store/records/RAlias.scala | 12 +- .../sharry/store/records/RAliasMember.scala | 12 +- .../sharry/store/records/RFileMeta.scala | 12 +- .../sharry/store/records/RInvitation.scala | 12 +- .../sharry/store/records/RPublishShare.scala | 10 +- .../scala/sharry/store/records/RShare.scala | 10 +- .../sharry/store/records/RShareFile.scala | 10 +- .../sharry/store/PermanentErrorTest.scala | 2 +- .../scala/sharry/store/StoreFixture.scala | 8 +- 117 files changed, 505 insertions(+), 436 deletions(-) diff --git a/build.sbt b/build.sbt index cff6a53d..9df6254e 100644 --- a/build.sbt +++ b/build.sbt @@ -22,6 +22,9 @@ val sharedSettings = Seq( "-feature", "-Werror", // fail when there are warnings "-unchecked", + "-Wunused:imports", + "-Wunused:locals", + "-Wunused:explicits", "-Wvalue-discard" ), Compile / console / scalacOptions := Seq(), diff --git a/modules/backend/src/main/scala/sharry/backend/BackendApp.scala b/modules/backend/src/main/scala/sharry/backend/BackendApp.scala index e8a809bf..da47451e 100644 --- a/modules/backend/src/main/scala/sharry/backend/BackendApp.scala +++ b/modules/backend/src/main/scala/sharry/backend/BackendApp.scala @@ -2,10 +2,10 @@ package sharry.backend import scala.concurrent.ExecutionContext -import cats.effect._ +import cats.effect.* import fs2.io.file.Files -import sharry.backend.account._ +import sharry.backend.account.* import sharry.backend.alias.OAlias import sharry.backend.auth.Login import sharry.backend.config.Config diff --git a/modules/backend/src/main/scala/sharry/backend/account/NewAccount.scala b/modules/backend/src/main/scala/sharry/backend/account/NewAccount.scala index 323d7aa1..a8ab2330 100644 --- a/modules/backend/src/main/scala/sharry/backend/account/NewAccount.scala +++ b/modules/backend/src/main/scala/sharry/backend/account/NewAccount.scala @@ -1,9 +1,9 @@ package sharry.backend.account import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* -import sharry.common._ +import sharry.common.* case class NewAccount( id: Ident, diff --git a/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala b/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala index 9a106200..25ca3030 100644 --- a/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala +++ b/modules/backend/src/main/scala/sharry/backend/account/OAccount.scala @@ -1,18 +1,18 @@ package sharry.backend.account import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Stream import sharry.backend.PasswordCrypt -import sharry.backend.share.{Queries => ShareQueries} -import sharry.common._ +import sharry.backend.share.Queries as ShareQueries +import sharry.common.* import sharry.store.AddResult import sharry.store.Store -import sharry.store.records._ +import sharry.store.records.* -import doobie._ +import doobie.* trait OAccount[F[_]] { diff --git a/modules/backend/src/main/scala/sharry/backend/account/Queries.scala b/modules/backend/src/main/scala/sharry/backend/account/Queries.scala index 3259b4fd..fbab2394 100644 --- a/modules/backend/src/main/scala/sharry/backend/account/Queries.scala +++ b/modules/backend/src/main/scala/sharry/backend/account/Queries.scala @@ -2,13 +2,13 @@ package sharry.backend.account import fs2.Stream -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ -import sharry.store.records._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* +import sharry.store.records.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* object Queries { diff --git a/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala b/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala index 79039370..806394b3 100644 --- a/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala +++ b/modules/backend/src/main/scala/sharry/backend/alias/OAlias.scala @@ -1,18 +1,18 @@ package sharry.backend.alias import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Stream import sharry.backend.alias.OAlias.{AliasDetail, AliasInput} -import sharry.common._ +import sharry.common.* import sharry.store.AddResult import sharry.store.Store import sharry.store.records.RAlias import sharry.store.records.RAliasMember -import doobie._ +import doobie.* trait OAlias[F[_]] { diff --git a/modules/backend/src/main/scala/sharry/backend/auth/AddAccount.scala b/modules/backend/src/main/scala/sharry/backend/auth/AddAccount.scala index 87947bef..21cea225 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/AddAccount.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/AddAccount.scala @@ -1,11 +1,11 @@ package sharry.backend.auth import cats.data.Kleisli -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.account.{NewAccount, OAccount} -import sharry.common._ +import sharry.common.* import sharry.store.records.RAccount object AddAccount { diff --git a/modules/backend/src/main/scala/sharry/backend/auth/AuthConfig.scala b/modules/backend/src/main/scala/sharry/backend/auth/AuthConfig.scala index 4125d64d..bee1ac9e 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/AuthConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/AuthConfig.scala @@ -1,5 +1,5 @@ package sharry.backend.auth -import sharry.common._ +import sharry.common.* import scodec.bits.ByteVector diff --git a/modules/backend/src/main/scala/sharry/backend/auth/AuthToken.scala b/modules/backend/src/main/scala/sharry/backend/auth/AuthToken.scala index d82d93b3..dcf48f8a 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/AuthToken.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/AuthToken.scala @@ -2,11 +2,11 @@ package sharry.backend.auth import java.time.Instant -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.Common -import sharry.backend.auth.AuthToken._ +import sharry.backend.auth.AuthToken.* import sharry.common.util.SignUtil import sharry.common.{AccountId, Duration} diff --git a/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala index 67c980f5..3be19889 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/CommandAuth.scala @@ -1,15 +1,15 @@ package sharry.backend.auth -import scala.sys.process._ +import scala.sys.process.* import cats.data.Kleisli -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.common._ +import sharry.common.* -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.implicits.* +import yamusca.imports.* final class CommandAuth[F[_]: Async]( cfg: AuthConfig, diff --git a/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala index 5d994524..f233a27b 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/FixedAuth.scala @@ -1,10 +1,10 @@ package sharry.backend.auth -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.backend.account._ -import sharry.common._ +import sharry.backend.account.* +import sharry.common.* /** Provides authentication from the configuration. * diff --git a/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala index 50e66077..5b9dcc2b 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/HttpAuth.scala @@ -3,13 +3,13 @@ package sharry.backend.auth import java.nio.charset.StandardCharsets import cats.data.Kleisli -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.common._ +import sharry.common.* -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.implicits.* +import yamusca.imports.* final class HttpAuth[F[_]: Async]( cfg: AuthConfig, diff --git a/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala index c462f8d1..6c5c3a4a 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/HttpBasicAuth.scala @@ -1,13 +1,13 @@ package sharry.backend.auth import java.nio.charset.StandardCharsets -import java.{util => ju} +import java.util as ju import cats.data.Kleisli -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.common._ +import sharry.common.* final class HttpBasicAuth[F[_]: Async]( cfg: AuthConfig, diff --git a/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala b/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala index a8d3127f..649c73f6 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/InternalAuth.scala @@ -1,12 +1,12 @@ package sharry.backend.auth import cats.data.Kleisli -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.PasswordCrypt import sharry.backend.account.OAccount -import sharry.common._ +import sharry.common.* import sharry.store.records.RAccount final class InternalAuth[F[_]: Async](cfg: AuthConfig, op: OAccount[F]) { diff --git a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala index 8ea92a3f..c83ce96c 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/Login.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/Login.scala @@ -2,8 +2,8 @@ package sharry.backend.auth import cats.data.Kleisli import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.account.OAccount import sharry.common.Ident diff --git a/modules/backend/src/main/scala/sharry/backend/auth/LoginModule.scala b/modules/backend/src/main/scala/sharry/backend/auth/LoginModule.scala index b3e6e89b..3b10054b 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/LoginModule.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/LoginModule.scala @@ -5,10 +5,10 @@ import cats.Monad import cats.data.Kleisli import cats.data.OptionT import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* import sharry.backend.account.OAccount -import sharry.common._ +import sharry.common.* object LoginModule { diff --git a/modules/backend/src/main/scala/sharry/backend/auth/UserPassData.scala b/modules/backend/src/main/scala/sharry/backend/auth/UserPassData.scala index 26402aee..3d1c2be9 100644 --- a/modules/backend/src/main/scala/sharry/backend/auth/UserPassData.scala +++ b/modules/backend/src/main/scala/sharry/backend/auth/UserPassData.scala @@ -1,10 +1,10 @@ package sharry.backend.auth -import sharry.backend.mustache.YamuscaCommon._ +import sharry.backend.mustache.YamuscaCommon.* import sharry.common.Password -import yamusca.derive._ -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.derive.* +import yamusca.implicits.* +import yamusca.imports.* case class UserPassData(user: String, pass: Password) {} diff --git a/modules/backend/src/main/scala/sharry/backend/config/Config.scala b/modules/backend/src/main/scala/sharry/backend/config/Config.scala index 6a814622..2549eb3d 100644 --- a/modules/backend/src/main/scala/sharry/backend/config/Config.scala +++ b/modules/backend/src/main/scala/sharry/backend/config/Config.scala @@ -1,7 +1,7 @@ package sharry.backend.config import cats.data.ValidatedNec -import cats.syntax.all._ +import cats.syntax.all.* import sharry.backend.auth.AuthConfig import sharry.backend.job.CleanupConfig diff --git a/modules/backend/src/main/scala/sharry/backend/config/FilesConfig.scala b/modules/backend/src/main/scala/sharry/backend/config/FilesConfig.scala index 6d8ffd9f..e8d3dd42 100644 --- a/modules/backend/src/main/scala/sharry/backend/config/FilesConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/config/FilesConfig.scala @@ -1,7 +1,7 @@ package sharry.backend.config import cats.data.{Validated, ValidatedNec} -import cats.syntax.all._ +import cats.syntax.all.* import sharry.common.Ident import sharry.store.FileStoreConfig diff --git a/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala b/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala index c80a2e64..a77626a4 100644 --- a/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala +++ b/modules/backend/src/main/scala/sharry/backend/files/OFiles.scala @@ -1,8 +1,8 @@ package sharry.backend.files import cats.data.OptionT -import cats.effect._ -import cats.syntax.all._ +import cats.effect.* +import cats.syntax.all.* import sharry.backend.config.FilesConfig import sharry.common.Ident diff --git a/modules/backend/src/main/scala/sharry/backend/job/CleanupConfig.scala b/modules/backend/src/main/scala/sharry/backend/job/CleanupConfig.scala index ca9578fe..2d075326 100644 --- a/modules/backend/src/main/scala/sharry/backend/job/CleanupConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/job/CleanupConfig.scala @@ -1,5 +1,5 @@ package sharry.backend.job -import sharry.common._ +import sharry.common.* case class CleanupConfig(enabled: Boolean, interval: Duration, invalidAge: Duration) {} diff --git a/modules/backend/src/main/scala/sharry/backend/job/PeriodicCleanup.scala b/modules/backend/src/main/scala/sharry/backend/job/PeriodicCleanup.scala index 6639e247..5348f0b4 100644 --- a/modules/backend/src/main/scala/sharry/backend/job/PeriodicCleanup.scala +++ b/modules/backend/src/main/scala/sharry/backend/job/PeriodicCleanup.scala @@ -1,11 +1,11 @@ package sharry.backend.job -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Stream -import sharry.backend.share._ -import sharry.backend.signup._ +import sharry.backend.share.* +import sharry.backend.signup.* import sharry.logging.Logger object PeriodicCleanup { diff --git a/modules/backend/src/main/scala/sharry/backend/mail/MailConfig.scala b/modules/backend/src/main/scala/sharry/backend/mail/MailConfig.scala index c8c2c401..e36cbe6f 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/MailConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/MailConfig.scala @@ -1,9 +1,9 @@ package sharry.backend.mail -import sharry.common._ +import sharry.common.* -import emil.{MailConfig => EmilConfig, _} -import yamusca.imports._ +import emil.{MailConfig as EmilConfig, *} +import yamusca.imports.* case class MailConfig( enabled: Boolean, diff --git a/modules/backend/src/main/scala/sharry/backend/mail/NotifyData.scala b/modules/backend/src/main/scala/sharry/backend/mail/NotifyData.scala index 45cc00aa..f894053f 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/NotifyData.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/NotifyData.scala @@ -1,7 +1,7 @@ package sharry.backend.mail import sharry.backend.mail.NotifyData.AccountInfo -import sharry.common._ +import sharry.common.* final case class NotifyData( aliasId: Ident, diff --git a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala index 16833c79..2105902a 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/OMail.scala @@ -2,17 +2,17 @@ package sharry.backend.mail import cats.data.EitherT import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.mail.MailConfig.MailTpl -import sharry.common._ +import sharry.common.* import sharry.store.Store -import emil.builder._ -import emil.javamail.syntax._ -import emil.{MailConfig => _, _} -import yamusca.implicits._ +import emil.builder.* +import emil.javamail.syntax.* +import emil.{MailConfig as _, *} +import yamusca.implicits.* trait OMail[F[_]] { @@ -90,7 +90,7 @@ object OMail { ) ) } - res <- OptionT.liftF(templates.traverse((send).tupled)) + res <- OptionT.liftF(templates.traverse(send.tupled)) failedReceiver = res .filter(_.isError) .flatMap(_.receiver) diff --git a/modules/backend/src/main/scala/sharry/backend/mail/Queries.scala b/modules/backend/src/main/scala/sharry/backend/mail/Queries.scala index 80d3f8c8..12f410e7 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/Queries.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/Queries.scala @@ -2,13 +2,13 @@ package sharry.backend.mail import cats.data.OptionT -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ -import sharry.store.records._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* +import sharry.store.records.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* import emil.MailAddress object Queries { diff --git a/modules/backend/src/main/scala/sharry/backend/mail/TemplateData.scala b/modules/backend/src/main/scala/sharry/backend/mail/TemplateData.scala index d2dcaac2..3b3879db 100644 --- a/modules/backend/src/main/scala/sharry/backend/mail/TemplateData.scala +++ b/modules/backend/src/main/scala/sharry/backend/mail/TemplateData.scala @@ -1,11 +1,11 @@ package sharry.backend.mail -import sharry.backend.mustache.YamuscaCommon._ -import sharry.common._ +import sharry.backend.mustache.YamuscaCommon.* +import sharry.common.* -import yamusca.derive._ -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.derive.* +import yamusca.implicits.* +import yamusca.imports.* case class TemplateData( user: Ident, diff --git a/modules/backend/src/main/scala/sharry/backend/mustache/YamuscaCommon.scala b/modules/backend/src/main/scala/sharry/backend/mustache/YamuscaCommon.scala index 0dd50a39..6b8a1ea4 100644 --- a/modules/backend/src/main/scala/sharry/backend/mustache/YamuscaCommon.scala +++ b/modules/backend/src/main/scala/sharry/backend/mustache/YamuscaCommon.scala @@ -1,8 +1,8 @@ package sharry.backend.mustache -import sharry.common._ +import sharry.common.* -import yamusca.imports._ +import yamusca.imports.* trait YamuscaCommon { diff --git a/modules/backend/src/main/scala/sharry/backend/share/ByteResult.scala b/modules/backend/src/main/scala/sharry/backend/share/ByteResult.scala index 452b1f38..68be3e5b 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ByteResult.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ByteResult.scala @@ -1,7 +1,7 @@ package sharry.backend.share import cats.data.OptionT -import cats.effect._ +import cats.effect.* import sharry.common.Ident import sharry.store.Store diff --git a/modules/backend/src/main/scala/sharry/backend/share/DescriptionTemplate.scala b/modules/backend/src/main/scala/sharry/backend/share/DescriptionTemplate.scala index f071d3dd..fec3dad7 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/DescriptionTemplate.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/DescriptionTemplate.scala @@ -1,11 +1,11 @@ package sharry.backend.share import sharry.backend.mustache.YamuscaCommon -import sharry.common._ +import sharry.common.* -import yamusca.derive._ -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.derive.* +import yamusca.implicits.* +import yamusca.imports.* final class DescriptionTemplate(sd: ShareDetail) { diff --git a/modules/backend/src/main/scala/sharry/backend/share/FileData.scala b/modules/backend/src/main/scala/sharry/backend/share/FileData.scala index e4991e96..96d9614a 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/FileData.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/FileData.scala @@ -1,6 +1,6 @@ package sharry.backend.share -import sharry.common._ +import sharry.common.* case class FileData( id: Ident, diff --git a/modules/backend/src/main/scala/sharry/backend/share/OShare.scala b/modules/backend/src/main/scala/sharry/backend/share/OShare.scala index e8a4cb3d..df9e63f1 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/OShare.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/OShare.scala @@ -1,17 +1,17 @@ package sharry.backend.share import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Stream import sharry.backend.PasswordCrypt -import sharry.common._ +import sharry.common.* import sharry.logging.Logger import sharry.store.AddResult import sharry.store.PermanentError import sharry.store.Store -import sharry.store.records._ +import sharry.store.records.* import binny.{ByteRange, ChunkDef, Hint} import scodec.bits.ByteVector diff --git a/modules/backend/src/main/scala/sharry/backend/share/Queries.scala b/modules/backend/src/main/scala/sharry/backend/share/Queries.scala index 8a1f34c4..48d90b56 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/Queries.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/Queries.scala @@ -1,18 +1,18 @@ package sharry.backend.share import cats.data.OptionT -import cats.effect._ -import cats.syntax.all._ +import cats.effect.* +import cats.syntax.all.* import fs2.Stream -import sharry.common._ +import sharry.common.* import sharry.store.Store -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ -import sharry.store.records._ +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* +import sharry.store.records.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* object Queries { val logger = sharry.logging.getLogger[ConnectionIO] diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareConfig.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareConfig.scala index ae39920f..09adbd57 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareConfig.scala @@ -1,6 +1,6 @@ package sharry.backend.share -import sharry.common._ +import sharry.common.* import sharry.store.DomainCheckConfig case class ShareConfig( diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareData.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareData.scala index efd69761..5b60c360 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareData.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareData.scala @@ -2,7 +2,7 @@ package sharry.backend.share import fs2.Stream -import sharry.common._ +import sharry.common.* case class ShareData[F[_]]( validity: Duration, diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareDetail.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareDetail.scala index 555c050d..8d6a9d83 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareDetail.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareDetail.scala @@ -1,7 +1,7 @@ package sharry.backend.share import sharry.common.LenientUri -import sharry.store.records._ +import sharry.store.records.* case class ShareDetail( share: RShare, diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareId.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareId.scala index cab54010..41f9fee7 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareId.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareId.scala @@ -1,6 +1,6 @@ package sharry.backend.share -import sharry.common._ +import sharry.common.* sealed trait ShareId { diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareItem.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareItem.scala index 5b9aeeec..dd29b902 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareItem.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareItem.scala @@ -1,6 +1,6 @@ package sharry.backend.share -import sharry.common._ +import sharry.common.* import sharry.store.records.RShare case class ShareItem( diff --git a/modules/backend/src/main/scala/sharry/backend/share/ShareResult.scala b/modules/backend/src/main/scala/sharry/backend/share/ShareResult.scala index 70e64204..686d0e8c 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/ShareResult.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/ShareResult.scala @@ -1,7 +1,7 @@ package sharry.backend.share import cats.Applicative -import cats.implicits._ +import cats.implicits.* sealed trait ShareResult[+A] { diff --git a/modules/backend/src/main/scala/sharry/backend/share/UploadResult.scala b/modules/backend/src/main/scala/sharry/backend/share/UploadResult.scala index 67db1977..cb49ba57 100644 --- a/modules/backend/src/main/scala/sharry/backend/share/UploadResult.scala +++ b/modules/backend/src/main/scala/sharry/backend/share/UploadResult.scala @@ -1,9 +1,9 @@ package sharry.backend.share import cats.Applicative -import cats.implicits._ +import cats.implicits.* -import sharry.common._ +import sharry.common.* sealed trait UploadResult[+A] { diff --git a/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala b/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala index 13a50e9e..bb1ae24f 100644 --- a/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala +++ b/modules/backend/src/main/scala/sharry/backend/signup/OSignup.scala @@ -1,10 +1,10 @@ package sharry.backend.signup -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.backend.account._ -import sharry.common._ +import sharry.backend.account.* +import sharry.common.* import sharry.store.records.RInvitation import sharry.store.{AddResult, Store} diff --git a/modules/backend/src/main/scala/sharry/backend/signup/SignupConfig.scala b/modules/backend/src/main/scala/sharry/backend/signup/SignupConfig.scala index ca88c2a7..c57a6d76 100644 --- a/modules/backend/src/main/scala/sharry/backend/signup/SignupConfig.scala +++ b/modules/backend/src/main/scala/sharry/backend/signup/SignupConfig.scala @@ -1,6 +1,6 @@ package sharry.backend.signup -import sharry.common._ +import sharry.common.* case class SignupConfig(mode: SignupMode, inviteTime: Duration, invitePassword: Password) diff --git a/modules/backend/src/test/scala/sharry/backend/auth/LoginModuleTest.scala b/modules/backend/src/test/scala/sharry/backend/auth/LoginModuleTest.scala index 5e5831d2..f7e42ca6 100644 --- a/modules/backend/src/test/scala/sharry/backend/auth/LoginModuleTest.scala +++ b/modules/backend/src/test/scala/sharry/backend/auth/LoginModuleTest.scala @@ -1,20 +1,20 @@ package sharry.backend.auth import cats.data.Kleisli -import cats.effect._ +import cats.effect.* import cats.effect.unsafe.implicits.global -import cats.implicits._ +import cats.implicits.* import sharry.backend.account.OAccount import sharry.backend.auth.AddAccount.AccountOps -import sharry.common._ +import sharry.common.* import sharry.store.Store import sharry.store.StoreFixture import sharry.store.doobie.Sql import sharry.store.records.RAccount -import _root_.doobie._ -import munit._ +import _root_.doobie.* +import munit.* import scodec.bits.ByteVector class LoginModuleTest extends FunSuite { diff --git a/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala b/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala index 70004b16..90f256d6 100644 --- a/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala +++ b/modules/backend/src/test/scala/sharry/backend/mail/QueriesTest.scala @@ -1,13 +1,13 @@ package sharry.backend.mail -import cats.effect._ +import cats.effect.* -import sharry.common._ -import sharry.store._ +import sharry.common.* +import sharry.store.* import sharry.store.records.RAccount import emil.MailAddress -import munit._ +import munit.* class QueriesTest extends FunSuite with StoreFixture { diff --git a/modules/common/src/main/scala/sharry/common/AccountId.scala b/modules/common/src/main/scala/sharry/common/AccountId.scala index db618a88..b0eaca9a 100644 --- a/modules/common/src/main/scala/sharry/common/AccountId.scala +++ b/modules/common/src/main/scala/sharry/common/AccountId.scala @@ -1,6 +1,6 @@ package sharry.common -import cats.implicits._ +import cats.implicits.* case class AccountId(id: Ident, userLogin: Ident, admin: Boolean, alias: Option[Ident]) { diff --git a/modules/common/src/main/scala/sharry/common/AccountState.scala b/modules/common/src/main/scala/sharry/common/AccountState.scala index 4044b598..1c5e330e 100644 --- a/modules/common/src/main/scala/sharry/common/AccountState.scala +++ b/modules/common/src/main/scala/sharry/common/AccountState.scala @@ -1,6 +1,6 @@ package sharry.common -import io.circe._ +import io.circe.* sealed trait AccountState { self: Product => final def name: String = diff --git a/modules/common/src/main/scala/sharry/common/BaseJsonCodecs.scala b/modules/common/src/main/scala/sharry/common/BaseJsonCodecs.scala index d0edb896..59a3d025 100644 --- a/modules/common/src/main/scala/sharry/common/BaseJsonCodecs.scala +++ b/modules/common/src/main/scala/sharry/common/BaseJsonCodecs.scala @@ -2,7 +2,7 @@ package sharry.common import java.time.Instant -import io.circe._ +import io.circe.* object BaseJsonCodecs { diff --git a/modules/common/src/main/scala/sharry/common/Duration.scala b/modules/common/src/main/scala/sharry/common/Duration.scala index 815ce3b0..382a43ef 100644 --- a/modules/common/src/main/scala/sharry/common/Duration.scala +++ b/modules/common/src/main/scala/sharry/common/Duration.scala @@ -1,12 +1,12 @@ package sharry.common -import java.time.{Duration => JDur} +import java.time.Duration as JDur import java.util.concurrent.TimeUnit -import scala.concurrent.duration.{Duration => SDur, FiniteDuration} +import scala.concurrent.duration.{Duration as SDur, FiniteDuration} import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* import io.circe.Decoder import io.circe.Encoder diff --git a/modules/common/src/main/scala/sharry/common/EnvMode.scala b/modules/common/src/main/scala/sharry/common/EnvMode.scala index 4a57dada..a32420e5 100644 --- a/modules/common/src/main/scala/sharry/common/EnvMode.scala +++ b/modules/common/src/main/scala/sharry/common/EnvMode.scala @@ -1,6 +1,6 @@ package sharry.common -import cats.implicits._ +import cats.implicits.* sealed trait EnvMode { self: Product => diff --git a/modules/common/src/main/scala/sharry/common/LenientUri.scala b/modules/common/src/main/scala/sharry/common/LenientUri.scala index 28bc2fd4..6e21b6d4 100644 --- a/modules/common/src/main/scala/sharry/common/LenientUri.scala +++ b/modules/common/src/main/scala/sharry/common/LenientUri.scala @@ -5,9 +5,9 @@ import java.net.URL import java.net.URLEncoder import cats.data.NonEmptyList +import cats.effect.* import cats.effect.Resource -import cats.effect._ -import cats.implicits._ +import cats.implicits.* import fs2.Stream import sharry.common.LenientUri.Path diff --git a/modules/common/src/main/scala/sharry/common/SignupMode.scala b/modules/common/src/main/scala/sharry/common/SignupMode.scala index ccc2c231..12000f65 100644 --- a/modules/common/src/main/scala/sharry/common/SignupMode.scala +++ b/modules/common/src/main/scala/sharry/common/SignupMode.scala @@ -1,6 +1,6 @@ package sharry.common -import io.circe._ +import io.circe.* sealed trait SignupMode { self: Product => final def name: String = diff --git a/modules/common/src/main/scala/sharry/common/ThreadFactories.scala b/modules/common/src/main/scala/sharry/common/ThreadFactories.scala index 64206f98..a6ed5cbc 100644 --- a/modules/common/src/main/scala/sharry/common/ThreadFactories.scala +++ b/modules/common/src/main/scala/sharry/common/ThreadFactories.scala @@ -6,9 +6,9 @@ import java.util.concurrent.ForkJoinWorkerThread import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.{Executors, ThreadFactory} -import scala.concurrent._ +import scala.concurrent.* -import cats.effect._ +import cats.effect.* object ThreadFactories { diff --git a/modules/common/src/main/scala/sharry/common/syntax/StreamSyntax.scala b/modules/common/src/main/scala/sharry/common/syntax/StreamSyntax.scala index 43320501..3dac6d57 100644 --- a/modules/common/src/main/scala/sharry/common/syntax/StreamSyntax.scala +++ b/modules/common/src/main/scala/sharry/common/syntax/StreamSyntax.scala @@ -1,11 +1,11 @@ package sharry.common.syntax import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* import fs2.Stream -import io.circe._ -import io.circe.parser._ +import io.circe.* +import io.circe.parser.* trait StreamSyntax { diff --git a/modules/common/src/main/scala/sharry/common/syntax/StringSyntax.scala b/modules/common/src/main/scala/sharry/common/syntax/StringSyntax.scala index d0af4148..cc109a7a 100644 --- a/modules/common/src/main/scala/sharry/common/syntax/StringSyntax.scala +++ b/modules/common/src/main/scala/sharry/common/syntax/StringSyntax.scala @@ -1,9 +1,9 @@ package sharry.common.syntax -import cats.implicits._ +import cats.implicits.* import io.circe.Decoder -import io.circe.parser._ +import io.circe.parser.* trait StringSyntax { diff --git a/modules/common/src/main/scala/sharry/common/util/Random.scala b/modules/common/src/main/scala/sharry/common/util/Random.scala index 2bf55c32..d0f38481 100644 --- a/modules/common/src/main/scala/sharry/common/util/Random.scala +++ b/modules/common/src/main/scala/sharry/common/util/Random.scala @@ -1,6 +1,6 @@ package sharry.common.util -import cats.effect._ +import cats.effect.* import scodec.bits.ByteVector diff --git a/modules/logging/api/src/main/scala/sharry/logging/AndThenLogger.scala b/modules/logging/api/src/main/scala/sharry/logging/AndThenLogger.scala index 6a107e1c..83c31a24 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/AndThenLogger.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/AndThenLogger.scala @@ -7,7 +7,7 @@ package sharry.logging import cats.data.NonEmptyList -import cats.syntax.all._ +import cats.syntax.all.* import cats.{Applicative, Id} final private[logging] class AndThenLogger[F[_]: Applicative]( diff --git a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala index a0a80614..cc053345 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LazyMap.scala @@ -2,7 +2,7 @@ package sharry.logging import sharry.logging.LazyMap.Val -final class LazyMap[A, B] private( +final class LazyMap[A, B] private ( private val values: Map[A, Val[B]] ) { lazy val toMap: Map[A, B] = values.view.mapValues(_.value).toMap diff --git a/modules/logging/api/src/main/scala/sharry/logging/LogEvent.scala b/modules/logging/api/src/main/scala/sharry/logging/LogEvent.scala index f241169f..75c14151 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/LogEvent.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/LogEvent.scala @@ -7,7 +7,7 @@ package sharry.logging import io.circe.{Encoder, Json} -import sourcecode._ +import sourcecode.* final case class LogEvent( level: Level, diff --git a/modules/logging/api/src/main/scala/sharry/logging/Logger.scala b/modules/logging/api/src/main/scala/sharry/logging/Logger.scala index 4ea37d7e..6198d410 100644 --- a/modules/logging/api/src/main/scala/sharry/logging/Logger.scala +++ b/modules/logging/api/src/main/scala/sharry/logging/Logger.scala @@ -10,12 +10,12 @@ import java.io.PrintStream import java.time.Instant import cats.effect.{Ref, Sync} -import cats.syntax.applicative._ -import cats.syntax.functor._ -import cats.syntax.order._ +import cats.syntax.applicative.* +import cats.syntax.functor.* +import cats.syntax.order.* import cats.{Applicative, Id} -import sourcecode._ +import sourcecode.* trait Logger[F[_]] extends LoggerExtension[F] { diff --git a/modules/logging/scribe/src/main/scala/sharry/logging/package.scala b/modules/logging/scribe/src/main/scala/sharry/logging/package.scala index dfe729b8..7d1fd6b2 100644 --- a/modules/logging/scribe/src/main/scala/sharry/logging/package.scala +++ b/modules/logging/scribe/src/main/scala/sharry/logging/package.scala @@ -7,7 +7,7 @@ package sharry import cats.Id -import cats.effect._ +import cats.effect.* import sharry.logging.impl.ScribeWrapper diff --git a/modules/logging/scribe/src/test/scala/docspell/logging/TestLoggingConfig.scala b/modules/logging/scribe/src/test/scala/docspell/logging/TestLoggingConfig.scala index be4137c4..727ffeb6 100644 --- a/modules/logging/scribe/src/test/scala/docspell/logging/TestLoggingConfig.scala +++ b/modules/logging/scribe/src/test/scala/docspell/logging/TestLoggingConfig.scala @@ -6,7 +6,7 @@ package docspell.logging -import sharry.logging._ +import sharry.logging.* import sharry.logging.impl.ScribeConfigure import munit.Suite diff --git a/modules/restserver/src/main/scala/sharry/restserver/CookieData.scala b/modules/restserver/src/main/scala/sharry/restserver/CookieData.scala index 1d875e5f..681f225d 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/CookieData.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/CookieData.scala @@ -1,9 +1,9 @@ package sharry.restserver -import sharry.backend.auth._ -import sharry.common._ +import sharry.backend.auth.* +import sharry.common.* -import org.http4s._ +import org.http4s.* import org.typelevel.ci.CIString case class CookieData(auth: AuthToken) { diff --git a/modules/restserver/src/main/scala/sharry/restserver/Main.scala b/modules/restserver/src/main/scala/sharry/restserver/Main.scala index d013ffe1..b51c67e8 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/Main.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/Main.scala @@ -3,9 +3,9 @@ package sharry.restserver import java.nio.file.Path import java.nio.file.{Files, Paths} -import cats.effect._ +import cats.effect.* -import sharry.common._ +import sharry.common.* import sharry.logging.impl.ScribeConfigure import sharry.restserver.config.ConfigFile diff --git a/modules/restserver/src/main/scala/sharry/restserver/RestAppImpl.scala b/modules/restserver/src/main/scala/sharry/restserver/RestAppImpl.scala index c8863e69..df16ed67 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/RestAppImpl.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/RestAppImpl.scala @@ -2,8 +2,8 @@ package sharry.restserver import scala.concurrent.ExecutionContext -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.io.file.Files import sharry.backend.BackendApp diff --git a/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala b/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala index 2596940d..83d909db 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/RestServer.scala @@ -1,8 +1,8 @@ package sharry.restserver import cats.data.{Kleisli, OptionT} -import cats.effect._ -import cats.syntax.all._ +import cats.effect.* +import cats.syntax.all.* import fs2.io.file.Files import fs2.io.net.Network import fs2.{Pure, Stream} @@ -12,18 +12,17 @@ import sharry.common.LenientUri import sharry.logging.Logger import sharry.restserver.config.Config import sharry.restserver.http4s.EnvMiddleware -import sharry.restserver.routes._ -import sharry.restserver.webapp._ +import sharry.restserver.routes.* +import sharry.restserver.webapp.* -import org.http4s._ +import org.http4s.* import org.http4s.client.Client import org.http4s.dsl.Http4sDsl import org.http4s.ember.client.EmberClientBuilder import org.http4s.ember.server.EmberServerBuilder import org.http4s.headers.{Location, `Content-Length`, `Content-Type`} import org.http4s.server.Router -import org.http4s.server.middleware.{Logger => Http4sLogger} -import scribe.Scribe +import org.http4s.server.middleware.Logger as Http4sLogger object RestServer { def stream[F[_]: Async: Files: Network]( diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/Config.scala b/modules/restserver/src/main/scala/sharry/restserver/config/Config.scala index 8a481627..8f2d5492 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/Config.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/Config.scala @@ -1,10 +1,10 @@ package sharry.restserver.config import cats.data.{Validated, ValidatedNec} -import cats.syntax.all._ +import cats.syntax.all.* -import sharry.backend.config.{Config => BackendConfig} -import sharry.common._ +import sharry.backend.config.Config as BackendConfig +import sharry.common.* import sharry.logging.LogConfig import com.comcast.ip4s.{Host, Port} diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala index 85aafb3d..e8704590 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala @@ -1,21 +1,26 @@ package sharry.restserver.config -import cats.syntax.all._ -import com.typesafe.config.{ConfigValue as TCValue} -import org.http4s.Uri -import ciris._ -import com.comcast.ip4s.{Host, Port} -import sharry.common._ +import scala.jdk.CollectionConverters.* + import cats.Show +import cats.syntax.all.* + +import sharry.common.* import sharry.logging.Level import sharry.logging.LogConfig -import scala.jdk.CollectionConverters._ + +import ciris.* +import com.comcast.ip4s.{Host, Port} +import com.typesafe.config.ConfigValue as TCValue +import org.http4s.Uri import scodec.bits.ByteVector -private [config] trait ConfigDecoders: - extension [A,B](self: ConfigDecoder[A,B]) +private[config] trait ConfigDecoders: + extension [A, B](self: ConfigDecoder[A, B]) def emap[C](typeName: String)(f: B => Either[String, C])(using Show[B]) = - self.mapEither((key, b) => f(b).left.map(err => ConfigError.decode(typeName, key, b))) + self.mapEither((key, b) => + f(b).left.map(err => ConfigError.decode(typeName, key, b)) + ) given ConfigDecoder[TCValue, String] = ConfigDecoder[TCValue].map(_.atKey("a").getString("a")) @@ -32,15 +37,22 @@ private [config] trait ConfigDecoders: inner.asScala.toList.traverse(e => ConfigDecoder[TCValue, A].decode(cfgKey, e)) } - given [K, A](using ConfigDecoder[String, K], ConfigDecoder[TCValue, A]): ConfigDecoder[TCValue, Map[K, A]] = + given [K, A](using + ConfigDecoder[String, K], + ConfigDecoder[TCValue, A] + ): ConfigDecoder[TCValue, Map[K, A]] = ConfigDecoder[TCValue].mapEither { (cfgKey, cv) => val inner = cv.atKey("a").getConfig("a") - inner.root.keySet.asScala.toList.traverse { key => - val value = inner.getObject(key) - ConfigDecoder[String, K].decode(cfgKey, key).flatMap( k => - ConfigDecoder[TCValue, A].decode(cfgKey, value).map(v => k -> v) - ) - }.map(_.toMap) + inner.root.keySet.asScala.toList + .traverse { key => + val value = inner.getObject(key) + ConfigDecoder[String, K] + .decode(cfgKey, key) + .flatMap(k => + ConfigDecoder[TCValue, A].decode(cfgKey, value).map(v => k -> v) + ) + } + .map(_.toMap) } given [A](using ConfigDecoder[String, A]): ConfigDecoder[TCValue, A] = diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala index e842fb7c..4101413d 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala @@ -1,29 +1,36 @@ package sharry.restserver.config -import cats.syntax.all._ -import ciris._ -import org.http4s.Uri -import sharry.restserver.config.Hocon.HoconAt -import com.comcast.ip4s.{Host, Port} -import sharry.common._ +import scala.jdk.CollectionConverters.* + +import cats.syntax.all.* + +import sharry.backend.auth.AuthConfig +import sharry.common.* import sharry.logging.Level import sharry.logging.LogConfig import sharry.store.JdbcConfig + +import ciris.* +import com.comcast.ip4s.{Host, Port} +import org.http4s.Uri import scodec.bits.ByteVector -import sharry.backend.auth.AuthConfig -import scala.jdk.CollectionConverters._ -import cats.Applicative +@annotation.nowarn object ConfigValues extends ConfigDecoders: private val hocon = Hocon.at("sharry.restserver") private def senv(envName: String) = env(s"SHARRY_${envName}") private def key(hoconPath: String, envName: String) = hocon(hoconPath).as[String].or(senv(envName)) - private def keyMap[A, B](hoconPath: String, envName: String)(using ConfigDecoder[String, A], ConfigDecoder[String, B]) = + private def keyMap[A, B](hoconPath: String, envName: String)(using + ConfigDecoder[String, A], + ConfigDecoder[String, B] + ) = hocon(hoconPath).as[Map[A, B]] - private def keyList[A](hoconPath: String, envName: String)(using ConfigDecoder[String, A]) = + private def keyList[A](hoconPath: String, envName: String)(using + ConfigDecoder[String, A] + ) = hocon(hoconPath).as[List[A]] val baseUrl = key("base-url", "BASE_URL").as[Uri] @@ -35,8 +42,8 @@ object ConfigValues extends ConfigDecoders: } val fileDownload = { - val chunkSize = key("file-download.download-chunk-size", - "FILE_DOWNLOAD_CHUNK_SIZE").as[ByteSize] + val chunkSize = + key("file-download.download-chunk-size", "FILE_DOWNLOAD_CHUNK_SIZE").as[ByteSize] chunkSize.map(Config.FileDownload.apply) } @@ -56,21 +63,41 @@ object ConfigValues extends ConfigDecoders: val logo = key("webapp.app-logo", "WEBAPP_LOGO") val logoDark = key("webapp.app-logo-dark", "WEBAPP_LOGO_DARK") val footer = key("webapp.app-footer", "WEBAPP_FOOTER") - val footerVisible = key("webapp.app-footer-visible", "WEBAPP_FOOTER_VISIBLE").as[Boolean] + val footerVisible = + key("webapp.app-footer-visible", "WEBAPP_FOOTER_VISIBLE").as[Boolean] val chunkSize = key("webapp.chunk-size", "WEBAPP_CHUNK_SIZE").as[ByteSize] - val retryDelays= keyList[Duration]("webapp.retry-delays", "WEBAPP_RETRY_DELAYS") + val retryDelays = keyList[Duration]("webapp.retry-delays", "WEBAPP_RETRY_DELAYS") val welcomeMsg = key("webapp.welcome-message", "WEBAPP_WELCOME_MESSAGE") val defaultLang = key("webapp.default-language", "WEBAPP_DEFAULT_LANGUAGE") val authRenewal = key("webapp.auth-renewal", "WEBAPP_AUTH_RENEWAL").as[Duration] val initialPage = key("webapp.initial-page", "WEBAPP_INITIAL_PAGE") - val defaultValidity = key("webapp.default-validity", "WEBAPP_DEFAULT_VALIDITY").as[Duration] + val defaultValidity = + key("webapp.default-validity", "WEBAPP_DEFAULT_VALIDITY").as[Duration] val initialTheme = key("webapp.initial-theme", "WEBAPP_INITIAL_THEME") - val oauthRedirect = key("webapp.oauth-auto-redirect", "WEBAPP_OAUTH_AUTO_REDIRECT").as[Boolean] + val oauthRedirect = + key("webapp.oauth-auto-redirect", "WEBAPP_OAUTH_AUTO_REDIRECT").as[Boolean] val customHead = key("webapp.custom-head", "WEBAPP_CUSTOM_HEAD") - (name, icon, iconDark, logo, logoDark, footer, footerVisible, chunkSize, retryDelays, welcomeMsg, defaultLang, authRenewal, initialPage, defaultValidity, initialTheme, oauthRedirect, customHead).mapN(Config.Webapp.apply) + ( + name, + icon, + iconDark, + logo, + logoDark, + footer, + footerVisible, + chunkSize, + retryDelays, + welcomeMsg, + defaultLang, + authRenewal, + initialPage, + defaultValidity, + initialTheme, + oauthRedirect, + customHead + ).mapN(Config.Webapp.apply) } - val authFixed: ConfigValue[Effect, AuthConfig.Fixed] = { def k(p: String, e: String) = key(s"backend.auth.fixed.$p", s"BACKEND_AUTH_FIXED_$e") @@ -111,7 +138,8 @@ object ConfigValues extends ConfigDecoders: key(s"backend.auth.command.$p", s"BACKEND_AUTH_COMMAND_$e") val enabled = k("enabled", "ENABLED").as[Boolean] - val program = keyList[String]("backend.auth.command.program", "BACKEND_AUTH_COMMAND_PROGRAM") + val program = + keyList[String]("backend.auth.command.program", "BACKEND_AUTH_COMMAND_PROGRAM") val success = k("success", "SUCCESS").as[Int] val order = k("order", "ORDER").as[Int] (enabled, program, success, order).mapN(AuthConfig.Command.apply) @@ -138,7 +166,10 @@ object ConfigValues extends ConfigDecoders: def authOAuth(id: Ident) = { def k(p: String, e: String) = - key(s"backend.auth.oauth.${id.id}.$p", s"BACKEND_AUTH_OAUTH_${id.id.toUpperCase()}_$e") + key( + s"backend.auth.oauth.${id.id}.$p", + s"BACKEND_AUTH_OAUTH_${id.id.toUpperCase()}_$e" + ) val idkey = ConfigKey(s"oauth id key: ${id.id}") val enabled = k("enabled", "ENABLED").as[Boolean] val name = k("name", "NAME") @@ -151,14 +182,27 @@ object ConfigValues extends ConfigDecoders: val userEmailKey = k("user-email-key", "USER_EMAIL_KEY").option val clientId = k("client-id", "CLIENT_ID") val clientSecret = k("client-secret", "CLIENT_SECRET") - (ConfigValue.loaded(idkey, id), enabled, name, authorizeUrl, tokenUrl, userUrl, userIdkey, userEmailKey, scope, clientId, clientSecret, icon).mapN(AuthConfig.OAuth.apply) + ( + ConfigValue.loaded(idkey, id), + enabled, + name, + authorizeUrl, + tokenUrl, + userUrl, + userIdkey, + userEmailKey, + scope, + clientId, + clientSecret, + icon + ).mapN(AuthConfig.OAuth.apply) } val authOAuthKeys = { def stringsToIds(strs: List[String]) = strs.traverse(Ident.fromString) match - case Right(ids) => ConfigValue.loaded(ConfigKey(""), ids) - case Left(err) => ConfigValue.failed(ConfigError(err)) + case Right(ids) => ConfigValue.loaded(ConfigKey(""), ids) + case Left(err) => ConfigValue.failed(ConfigError(err)) val hoconKeys = hocon("backend.auth.oauth") @@ -166,8 +210,9 @@ object ConfigValues extends ConfigDecoders: .flatMap(stringsToIds) val envKeys = - senv("BACKEND_AUTH_OAUTH_IDS").map(s => s.split(',').toList.map(_.trim)) - .flatMap(stringsToIds) + senv("BACKEND_AUTH_OAUTH_IDS") + .map(s => s.split(',').toList.map(_.trim)) + .flatMap(stringsToIds) hoconKeys.or(envKeys) } @@ -175,15 +220,26 @@ object ConfigValues extends ConfigDecoders: val authOAuthSeq = authOAuthKeys.flatMap(ids => ids.foldLeft(ConfigValue.loaded(ConfigKey(""), List.empty[AuthConfig.OAuth])) { - (cv, id) => cv.flatMap(l => authOAuth(id).map(_ :: l)) - }) + (cv, id) => cv.flatMap(l => authOAuth(id).map(_ :: l)) + } + ) val auth = { def k(p: String, e: String) = key(s"backend.auth.$p", s"BACKEND_AUTH_$e") val serverSecret = k("server-secret", "SERVER_SECRET").as[ByteVector] val sessionValid = k("session-valid", "SESSION_VALID").as[Duration] - (serverSecret, sessionValid, authFixed, authHttp, authHttpBasic, authCommand, authProxy, authInternal, authOAuthSeq).mapN(AuthConfig.apply) + ( + serverSecret, + sessionValid, + authFixed, + authHttp, + authHttpBasic, + authCommand, + authProxy, + authInternal, + authOAuthSeq + ).mapN(AuthConfig.apply) } val jdbc = { @@ -193,5 +249,4 @@ object ConfigValues extends ConfigDecoders: (url, user, pass).mapN(JdbcConfig.apply) } - end ConfigValues diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala b/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala index b25a1227..b65b3f88 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/Hocon.scala @@ -1,9 +1,9 @@ package sharry.restserver.config -import com.typesafe.config.{Config, ConfigValue as TCValue} -import ciris._ +import ciris.* import com.typesafe.config.ConfigException import com.typesafe.config.ConfigFactory +import com.typesafe.config.{Config, ConfigValue as TCValue} private[config] object Hocon: final class HoconAt(config: Config, path: String): @@ -15,7 +15,7 @@ private[config] object Hocon: ConfigValue.loaded(ckey, value) catch case _: ConfigException.Missing => ConfigValue.missing(ckey) - case ex => ConfigValue.failed(ConfigError(ex.getMessage)) + case ex => ConfigValue.failed(ConfigError(ex.getMessage)) def at(config: Config)(path: String): HoconAt = HoconAt(config.resolve(), path) diff --git a/modules/restserver/src/main/scala/sharry/restserver/http4s/ClientRequestInfo.scala b/modules/restserver/src/main/scala/sharry/restserver/http4s/ClientRequestInfo.scala index e04310a2..b225f6bd 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/http4s/ClientRequestInfo.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/http4s/ClientRequestInfo.scala @@ -1,14 +1,14 @@ package sharry.restserver.http4s import cats.data.NonEmptyList -import cats.implicits._ +import cats.implicits.* -import sharry.common._ +import sharry.common.* import sharry.restserver.config.Config import com.comcast.ip4s.Port -import org.http4s._ -import org.http4s.headers._ +import org.http4s.* +import org.http4s.headers.* import org.typelevel.ci.CIString /** Obtain information about the client by inspecting the request. */ diff --git a/modules/restserver/src/main/scala/sharry/restserver/http4s/EnvMiddleware.scala b/modules/restserver/src/main/scala/sharry/restserver/http4s/EnvMiddleware.scala index 7cf8c48d..d2b23bfc 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/http4s/EnvMiddleware.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/http4s/EnvMiddleware.scala @@ -2,9 +2,9 @@ package sharry.restserver.http4s import cats.Functor -import sharry.common._ +import sharry.common.* -import org.http4s._ +import org.http4s.* object EnvMiddleware { diff --git a/modules/restserver/src/main/scala/sharry/restserver/http4s/NoCacheMiddleware.scala b/modules/restserver/src/main/scala/sharry/restserver/http4s/NoCacheMiddleware.scala index a3e827d5..f91a0264 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/http4s/NoCacheMiddleware.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/http4s/NoCacheMiddleware.scala @@ -4,10 +4,10 @@ import cats.Functor import cats.data.Kleisli import cats.data.NonEmptyList -import sharry.common._ +import sharry.common.* -import org.http4s._ -import org.http4s.headers._ +import org.http4s.* +import org.http4s.headers.* object NoCacheMiddleware { private val noCacheHeader = diff --git a/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala b/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala index f6a3bdc9..e7cd368a 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/oauth/CodeFlow.scala @@ -1,17 +1,17 @@ package sharry.restserver.oauth import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.auth.AuthConfig import sharry.common.Ident import sharry.logging.Logger import io.circe.Json -import org.http4s.Method._ -import org.http4s._ -import org.http4s.circe.CirceEntityCodec._ +import org.http4s.* +import org.http4s.Method.* +import org.http4s.circe.CirceEntityCodec.* import org.http4s.client.Client import org.http4s.client.dsl.Http4sClientDsl import org.http4s.client.middleware.RequestLogger diff --git a/modules/restserver/src/main/scala/sharry/restserver/oauth/StateParam.scala b/modules/restserver/src/main/scala/sharry/restserver/oauth/StateParam.scala index dad4531c..ff568fc4 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/oauth/StateParam.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/oauth/StateParam.scala @@ -1,7 +1,7 @@ package sharry.restserver.oauth -import cats.effect._ -import cats.syntax.all._ +import cats.effect.* +import cats.syntax.all.* import sharry.common.util.{Random, SignUtil} diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/AccountRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/AccountRoutes.scala index 02c77147..f8922712 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/AccountRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/AccountRoutes.scala @@ -1,18 +1,18 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.account.{AccountItem, NewAccount} -import sharry.common._ -import sharry.restapi.model._ +import sharry.common.* +import sharry.restapi.model.* import sharry.store.records.ModAccount import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object AccountRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/AliasMemberRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/AliasMemberRoutes.scala index 8c4e0cb0..10c8a778 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/AliasMemberRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/AliasMemberRoutes.scala @@ -1,15 +1,15 @@ package sharry.restserver.routes -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.account.AccountItem import sharry.backend.auth.AuthToken -import sharry.restapi.model._ +import sharry.restapi.model.* import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object AliasMemberRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/AliasRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/AliasRoutes.scala index 178f0551..db2b1735 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/AliasRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/AliasRoutes.scala @@ -1,19 +1,19 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.alias.OAlias import sharry.backend.auth.AuthToken -import sharry.common._ -import sharry.restapi.model._ +import sharry.common.* +import sharry.restapi.model.* import sharry.store.records.RAlias import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object AliasRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/Authenticate.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/Authenticate.scala index 3f8fbca6..2376cae5 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/Authenticate.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/Authenticate.scala @@ -1,16 +1,16 @@ package sharry.restserver.routes -import cats.data._ -import cats.effect._ -import cats.implicits._ +import cats.data.* +import cats.effect.* +import cats.implicits.* -import sharry.backend.auth._ -import sharry.restserver._ +import sharry.backend.auth.* +import sharry.restserver.* -import org.http4s._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl -import org.http4s.server._ +import org.http4s.server.* import org.typelevel.ci.CIString object Authenticate { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/ByteResponse.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/ByteResponse.scala index cd68a3cf..3f3d74f8 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/ByteResponse.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/ByteResponse.scala @@ -2,18 +2,18 @@ package sharry.restserver.routes import cats.data.OptionT import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* import fs2.Stream import sharry.backend.BackendApp -import sharry.backend.share._ -import sharry.common._ +import sharry.backend.share.* +import sharry.common.* import sharry.store.records.RFileMeta import binny.ByteRange -import org.http4s._ +import org.http4s.* import org.http4s.dsl.Http4sDsl -import org.http4s.headers._ +import org.http4s.headers.* import org.typelevel.ci.CIString object ByteResponse { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/Conv.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/Conv.scala index c0e2d5a6..8a84d98b 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/Conv.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/Conv.scala @@ -1,7 +1,7 @@ package sharry.restserver.routes import cats.data.NonEmptyList -import cats.implicits._ +import cats.implicits.* import cats.{ApplicativeError, MonadError} import sharry.backend.share.UploadResult diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/InfoRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/InfoRoutes.scala index fcc717f9..ca9062a0 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/InfoRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/InfoRoutes.scala @@ -1,13 +1,13 @@ package sharry.restserver.routes -import cats.effect._ +import cats.effect.* -import sharry.restapi.model._ +import sharry.restapi.model.* import sharry.restserver.BuildInfo import sharry.restserver.config.Config import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object InfoRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/LoginRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/LoginRoutes.scala index b99857a3..b6f92fba 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/LoginRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/LoginRoutes.scala @@ -1,22 +1,22 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.account.NewAccount -import sharry.backend.auth._ -import sharry.common._ -import sharry.restapi.model._ -import sharry.restserver._ +import sharry.backend.auth.* +import sharry.common.* +import sharry.restapi.model.* +import sharry.restserver.* import sharry.restserver.config.Config import sharry.restserver.http4s.ClientRequestInfo import sharry.restserver.oauth.{CodeFlow, StateParam} -import org.http4s._ -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.* +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.client.Client import org.http4s.dsl.Http4sDsl import org.http4s.headers.Location diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/MailRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/MailRoutes.scala index 3c52736c..3dea0923 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/MailRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/MailRoutes.scala @@ -2,13 +2,13 @@ package sharry.restserver.routes import cats.data.EitherT import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.auth.AuthToken import sharry.backend.mail.{MailData, MailSendResult} -import sharry.common._ +import sharry.common.* import sharry.restapi.model.BasicResult import sharry.restapi.model.MailTemplate import sharry.restapi.model.SimpleMail @@ -16,11 +16,11 @@ import sharry.restserver.config.Config import sharry.restserver.http4s.ClientRequestInfo import emil.MailAddress -import emil.javamail.syntax._ +import emil.javamail.syntax.* import org.http4s.HttpRoutes import org.http4s.Request -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object MailRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/NotifyRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/NotifyRoutes.scala index 7b3e17e5..e7ff55c1 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/NotifyRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/NotifyRoutes.scala @@ -1,18 +1,18 @@ package sharry.restserver.routes -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.auth.AuthToken import sharry.backend.mail.NotifyResult -import sharry.common._ +import sharry.common.* import sharry.restapi.model.BasicResult import sharry.restserver.config.Config import sharry.restserver.http4s.ClientRequestInfo import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object NotifyRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/OpenShareRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/OpenShareRoutes.scala index d2e89442..44cd6b32 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/OpenShareRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/OpenShareRoutes.scala @@ -1,14 +1,14 @@ package sharry.restserver.routes -import cats.effect._ +import cats.effect.* import sharry.backend.BackendApp -import sharry.backend.share._ -import sharry.common._ +import sharry.backend.share.* +import sharry.common.* import sharry.restserver.config.Config import sharry.restserver.routes.headers.SharryPassword -import org.http4s._ +import org.http4s.* import org.http4s.dsl.Http4sDsl object OpenShareRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/RegisterRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/RegisterRoutes.scala index 395151fd..3cf08d9f 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/RegisterRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/RegisterRoutes.scala @@ -1,17 +1,17 @@ package sharry.restserver.routes -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.signup.OSignup.RegisterData import sharry.backend.signup.{NewInviteResult, SignupResult} -import sharry.restapi.model._ +import sharry.restapi.model.* import sharry.restserver.config.Config import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object RegisterRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/SettingRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/SettingRoutes.scala index 40f10d1e..bebb11bb 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/SettingRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/SettingRoutes.scala @@ -1,16 +1,16 @@ package sharry.restserver.routes -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.auth.AuthToken import sharry.common.AccountSource -import sharry.restapi.model._ +import sharry.restapi.model.* import org.http4s.HttpRoutes -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object SettingRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareDetailResponse.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareDetailResponse.scala index 823e7381..eb213377 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareDetailResponse.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareDetailResponse.scala @@ -1,20 +1,20 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.syntax.all._ +import cats.effect.* +import cats.syntax.all.* import sharry.backend.BackendApp -import sharry.backend.share._ -import sharry.common._ -import sharry.restapi.model.{ShareDetail => ShareDetailDto, _} +import sharry.backend.share.* +import sharry.common.* +import sharry.restapi.model.{ShareDetail as ShareDetailDto, *} import sharry.restserver.config.Config import sharry.restserver.http4s.ClientRequestInfo -import org.http4s._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl -import org.http4s.headers._ +import org.http4s.headers.* object ShareDetailResponse { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareRoutes.scala index 77769344..8ad1dda1 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareRoutes.scala @@ -1,21 +1,21 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.auth.AuthToken -import sharry.backend.share._ -import sharry.common._ -import sharry.restapi.model._ +import sharry.backend.share.* +import sharry.common.* +import sharry.restapi.model.* import sharry.restserver.config.Config import sharry.restserver.routes.headers.SharryPassword import sharry.store.AddResult -import org.http4s._ -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.* +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl object ShareRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareUploadRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareUploadRoutes.scala index 4a9255ac..01c46397 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/ShareUploadRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/ShareUploadRoutes.scala @@ -1,16 +1,16 @@ package sharry.restserver.routes import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Stream import sharry.backend.BackendApp import sharry.backend.auth.AuthToken import sharry.backend.share.{File, ShareData} -import sharry.common._ -import sharry.common.syntax.all._ -import sharry.restapi.model._ +import sharry.common.* +import sharry.common.syntax.all.* +import sharry.restapi.model.* import sharry.restserver.config.Config import sharry.restserver.http4s.ClientRequestInfo import sharry.restserver.routes.tus.TusRoutes @@ -18,8 +18,8 @@ import sharry.restserver.routes.tus.TusRoutes import org.http4s.HttpRoutes import org.http4s.Request import org.http4s.Uri -import org.http4s.circe.CirceEntityDecoder._ -import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.circe.CirceEntityDecoder.* +import org.http4s.circe.CirceEntityEncoder.* import org.http4s.dsl.Http4sDsl import org.http4s.headers.{`Content-Length`, `Content-Type`} import org.http4s.multipart.Multipart diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/tus/SharryFileLength.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/tus/SharryFileLength.scala index e27408df..08f4ddd4 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/tus/SharryFileLength.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/tus/SharryFileLength.scala @@ -2,7 +2,7 @@ package sharry.restserver.routes.tus import sharry.common.ByteSize -import org.http4s._ +import org.http4s.* import org.typelevel.ci.CIString object SharryFileLength { diff --git a/modules/restserver/src/main/scala/sharry/restserver/routes/tus/TusRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/routes/tus/TusRoutes.scala index f98d16d8..17700ad2 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/routes/tus/TusRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/routes/tus/TusRoutes.scala @@ -1,18 +1,18 @@ package sharry.restserver.routes.tus import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import sharry.backend.BackendApp import sharry.backend.auth.AuthToken import sharry.backend.share.{FileInfo, UploadResult} -import sharry.common._ +import sharry.common.* import sharry.restserver.config.Config -import org.http4s._ +import org.http4s.* import org.http4s.dsl.Http4sDsl -import org.http4s.headers._ +import org.http4s.headers.* import org.typelevel.ci.CIString object TusRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala index 633471f2..bda42a82 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/webapp/TemplateRoutes.scala @@ -3,9 +3,9 @@ package sharry.restserver.webapp import java.net.URL import java.util.concurrent.atomic.AtomicReference -import cats.effect._ -import cats.implicits._ -import fs2._ +import cats.effect.* +import cats.implicits.* +import fs2.* import fs2.io.file.{Files, Path} import sharry.logging.Logger @@ -13,16 +13,16 @@ import sharry.restapi.model.AppConfig import sharry.restserver.BuildInfo import sharry.restserver.config.Config import sharry.restserver.routes.InfoRoutes -import sharry.restserver.webapp.YamuscaConverter._ +import sharry.restserver.webapp.YamuscaConverter.* -import _root_.io.circe.syntax._ +import _root_.io.circe.syntax.* +import org.http4s.* import org.http4s.HttpRoutes -import org.http4s._ import org.http4s.dsl.Http4sDsl -import org.http4s.headers._ -import yamusca.derive._ -import yamusca.implicits._ -import yamusca.imports._ +import org.http4s.headers.* +import yamusca.derive.* +import yamusca.implicits.* +import yamusca.imports.* object TemplateRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/webapp/WebjarRoutes.scala b/modules/restserver/src/main/scala/sharry/restserver/webapp/WebjarRoutes.scala index 3d710b7b..e561f995 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/webapp/WebjarRoutes.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/webapp/WebjarRoutes.scala @@ -1,9 +1,9 @@ package sharry.restserver.webapp -import cats.effect._ +import cats.effect.* import org.http4s.HttpRoutes -import org.http4s.server.staticcontent._ +import org.http4s.server.staticcontent.* object WebjarRoutes { diff --git a/modules/restserver/src/main/scala/sharry/restserver/webapp/YamuscaConverter.scala b/modules/restserver/src/main/scala/sharry/restserver/webapp/YamuscaConverter.scala index 1c17773d..9e6fea34 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/webapp/YamuscaConverter.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/webapp/YamuscaConverter.scala @@ -4,9 +4,9 @@ import sharry.backend.mustache.YamuscaCommon import sharry.restapi.model.AppConfig import sharry.restapi.model.OAuthItem -import yamusca.derive._ -import yamusca.implicits._ -import yamusca.imports._ +import yamusca.derive.* +import yamusca.implicits.* +import yamusca.imports.* object YamuscaConverter extends YamuscaCommon { diff --git a/modules/restserver/src/test/scala/sharry/restserver/oauth/StateParamTest.scala b/modules/restserver/src/test/scala/sharry/restserver/oauth/StateParamTest.scala index d5c864fe..ade8aa3f 100644 --- a/modules/restserver/src/test/scala/sharry/restserver/oauth/StateParamTest.scala +++ b/modules/restserver/src/test/scala/sharry/restserver/oauth/StateParamTest.scala @@ -1,8 +1,8 @@ package sharry.restserver.oauth -import cats.effect._ +import cats.effect.* -import munit._ +import munit.* import scodec.bits.ByteVector class StateParamTest extends CatsEffectSuite { diff --git a/modules/store/src/main/scala/sharry/store/AddResult.scala b/modules/store/src/main/scala/sharry/store/AddResult.scala index cf423094..7e5d417b 100644 --- a/modules/store/src/main/scala/sharry/store/AddResult.scala +++ b/modules/store/src/main/scala/sharry/store/AddResult.scala @@ -1,6 +1,6 @@ package sharry.store -import sharry.store.AddResult._ +import sharry.store.AddResult.* sealed trait AddResult { def toEither: Either[Throwable, Unit] diff --git a/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala b/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala index 27ccf86d..f251423b 100644 --- a/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala +++ b/modules/store/src/main/scala/sharry/store/ComputeChecksum.scala @@ -1,14 +1,14 @@ package sharry.store -import cats.effect._ +import cats.effect.* import cats.effect.std.Queue -import cats.syntax.all._ +import cats.syntax.all.* import fs2.{Pipe, Stream} import sharry.common.{ByteSize, Ident, Timestamp} import sharry.store.records.RFileMeta -import binny._ +import binny.* import binny.util.Stopwatch trait ComputeChecksum[F[_]] { diff --git a/modules/store/src/main/scala/sharry/store/FileStore.scala b/modules/store/src/main/scala/sharry/store/FileStore.scala index 4fa44920..cc8ca1db 100644 --- a/modules/store/src/main/scala/sharry/store/FileStore.scala +++ b/modules/store/src/main/scala/sharry/store/FileStore.scala @@ -3,17 +3,17 @@ package sharry.store import javax.sql.DataSource import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* import fs2.Chunk import fs2.io.file.Files -import sharry.common._ +import sharry.common.* import sharry.store.doobie.AttributeStore import sharry.store.records.RFileMeta -import _root_.doobie._ -import binny._ +import _root_.doobie.* +import binny.* trait FileStore[F[_]] { diff --git a/modules/store/src/main/scala/sharry/store/FileStoreConfig.scala b/modules/store/src/main/scala/sharry/store/FileStoreConfig.scala index b9226676..f0a5aee1 100644 --- a/modules/store/src/main/scala/sharry/store/FileStoreConfig.scala +++ b/modules/store/src/main/scala/sharry/store/FileStoreConfig.scala @@ -3,7 +3,7 @@ package sharry.store import javax.sql.DataSource import cats.effect.Async -import cats.syntax.all._ +import cats.syntax.all.* import fs2.io.file.{Files, Path} import binny.ChunkedBinaryStore diff --git a/modules/store/src/main/scala/sharry/store/Store.scala b/modules/store/src/main/scala/sharry/store/Store.scala index 69beb8be..bd34cbb9 100644 --- a/modules/store/src/main/scala/sharry/store/Store.scala +++ b/modules/store/src/main/scala/sharry/store/Store.scala @@ -2,14 +2,14 @@ package sharry.store import scala.concurrent.ExecutionContext -import cats.effect._ -import fs2._ +import cats.effect.* +import fs2.* import fs2.io.file.Files import sharry.common.ByteSize import sharry.store.doobie.StoreImpl -import _root_.doobie._ +import _root_.doobie.* import _root_.doobie.hikari.HikariTransactor import _root_.doobie.util.log.{LogEvent, Success} import com.zaxxer.hikari.HikariDataSource diff --git a/modules/store/src/main/scala/sharry/store/doobie/AttributeStore.scala b/modules/store/src/main/scala/sharry/store/doobie/AttributeStore.scala index c8e653f3..d72a0457 100644 --- a/modules/store/src/main/scala/sharry/store/doobie/AttributeStore.scala +++ b/modules/store/src/main/scala/sharry/store/doobie/AttributeStore.scala @@ -1,15 +1,15 @@ package sharry.store.doobie import cats.data.OptionT -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.common._ +import sharry.common.* import sharry.store.records.RFileMeta -import binny._ -import doobie._ -import doobie.implicits._ +import binny.* +import doobie.* +import doobie.implicits.* import scodec.bits.ByteVector final private[store] class AttributeStore[F[_]: Sync](xa: Transactor[F]) { diff --git a/modules/store/src/main/scala/sharry/store/doobie/Column.scala b/modules/store/src/main/scala/sharry/store/doobie/Column.scala index 1abecc66..c1444d84 100644 --- a/modules/store/src/main/scala/sharry/store/doobie/Column.scala +++ b/modules/store/src/main/scala/sharry/store/doobie/Column.scala @@ -2,8 +2,8 @@ package sharry.store.doobie import sharry.common.CIIdent -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class Column(name: String, ns: String = "", alias: String = "") { diff --git a/modules/store/src/main/scala/sharry/store/doobie/DoobieMeta.scala b/modules/store/src/main/scala/sharry/store/doobie/DoobieMeta.scala index 10aded2c..9a568164 100644 --- a/modules/store/src/main/scala/sharry/store/doobie/DoobieMeta.scala +++ b/modules/store/src/main/scala/sharry/store/doobie/DoobieMeta.scala @@ -3,11 +3,11 @@ package sharry.store.doobie import java.time.format.DateTimeFormatter import java.time.{Instant, LocalDate} -import sharry.common._ -import sharry.common.syntax.all._ +import sharry.common.* +import sharry.common.syntax.all.* -import doobie._ -import doobie.implicits.legacy.instant._ +import doobie.* +import doobie.implicits.legacy.instant.* import io.circe.{Decoder, Encoder} import scodec.bits.ByteVector diff --git a/modules/store/src/main/scala/sharry/store/doobie/Sql.scala b/modules/store/src/main/scala/sharry/store/doobie/Sql.scala index d449655f..dffac223 100644 --- a/modules/store/src/main/scala/sharry/store/doobie/Sql.scala +++ b/modules/store/src/main/scala/sharry/store/doobie/Sql.scala @@ -2,8 +2,8 @@ package sharry.store.doobie import sharry.common.Timestamp -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* object Sql { diff --git a/modules/store/src/main/scala/sharry/store/doobie/StoreImpl.scala b/modules/store/src/main/scala/sharry/store/doobie/StoreImpl.scala index 78f93838..bbd3842a 100644 --- a/modules/store/src/main/scala/sharry/store/doobie/StoreImpl.scala +++ b/modules/store/src/main/scala/sharry/store/doobie/StoreImpl.scala @@ -1,13 +1,13 @@ package sharry.store.doobie -import cats.effect._ -import cats.implicits._ +import cats.effect.* +import cats.implicits.* -import sharry.store._ +import sharry.store.* import sharry.store.migrate.FlywayMigrate -import _root_.doobie._ -import _root_.doobie.implicits._ +import _root_.doobie.* +import _root_.doobie.implicits.* final class StoreImpl[F[_]: Async](jdbc: JdbcConfig, fs: FileStore[F], xa: Transactor[F]) extends Store[F] { diff --git a/modules/store/src/main/scala/sharry/store/records/ModAccount.scala b/modules/store/src/main/scala/sharry/store/records/ModAccount.scala index fcc4daf2..4bfba75b 100644 --- a/modules/store/src/main/scala/sharry/store/records/ModAccount.scala +++ b/modules/store/src/main/scala/sharry/store/records/ModAccount.scala @@ -1,6 +1,6 @@ package sharry.store.records -import sharry.common._ +import sharry.common.* case class ModAccount( state: AccountState, diff --git a/modules/store/src/main/scala/sharry/store/records/RAccount.scala b/modules/store/src/main/scala/sharry/store/records/RAccount.scala index 163b8136..a1ccae46 100644 --- a/modules/store/src/main/scala/sharry/store/records/RAccount.scala +++ b/modules/store/src/main/scala/sharry/store/records/RAccount.scala @@ -1,14 +1,14 @@ package sharry.store.records -import cats.implicits._ +import cats.implicits.* import fs2.Stream -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RAccount( id: Ident, diff --git a/modules/store/src/main/scala/sharry/store/records/RAlias.scala b/modules/store/src/main/scala/sharry/store/records/RAlias.scala index 47ffa6a2..34a452f9 100644 --- a/modules/store/src/main/scala/sharry/store/records/RAlias.scala +++ b/modules/store/src/main/scala/sharry/store/records/RAlias.scala @@ -1,15 +1,15 @@ package sharry.store.records import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* import fs2.Stream -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RAlias( id: Ident, diff --git a/modules/store/src/main/scala/sharry/store/records/RAliasMember.scala b/modules/store/src/main/scala/sharry/store/records/RAliasMember.scala index 04d069cb..fd0c51ea 100644 --- a/modules/store/src/main/scala/sharry/store/records/RAliasMember.scala +++ b/modules/store/src/main/scala/sharry/store/records/RAliasMember.scala @@ -1,14 +1,14 @@ package sharry.store.records import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RAliasMember( id: Ident, diff --git a/modules/store/src/main/scala/sharry/store/records/RFileMeta.scala b/modules/store/src/main/scala/sharry/store/records/RFileMeta.scala index c4416d86..bb7d5df1 100644 --- a/modules/store/src/main/scala/sharry/store/records/RFileMeta.scala +++ b/modules/store/src/main/scala/sharry/store/records/RFileMeta.scala @@ -1,13 +1,13 @@ package sharry.store.records -import cats.implicits._ +import cats.implicits.* -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* import scodec.bits.ByteVector case class RFileMeta( diff --git a/modules/store/src/main/scala/sharry/store/records/RInvitation.scala b/modules/store/src/main/scala/sharry/store/records/RInvitation.scala index 4783a3bc..c34dc316 100644 --- a/modules/store/src/main/scala/sharry/store/records/RInvitation.scala +++ b/modules/store/src/main/scala/sharry/store/records/RInvitation.scala @@ -1,14 +1,14 @@ package sharry.store.records import cats.effect.Sync -import cats.implicits._ +import cats.implicits.* -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RInvitation(id: Ident, created: Timestamp) {} diff --git a/modules/store/src/main/scala/sharry/store/records/RPublishShare.scala b/modules/store/src/main/scala/sharry/store/records/RPublishShare.scala index 09fc6d9c..3b3d841d 100644 --- a/modules/store/src/main/scala/sharry/store/records/RPublishShare.scala +++ b/modules/store/src/main/scala/sharry/store/records/RPublishShare.scala @@ -2,12 +2,12 @@ package sharry.store.records import cats.data.OptionT -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RPublishShare( id: Ident, diff --git a/modules/store/src/main/scala/sharry/store/records/RShare.scala b/modules/store/src/main/scala/sharry/store/records/RShare.scala index ca078e64..ed9a12c2 100644 --- a/modules/store/src/main/scala/sharry/store/records/RShare.scala +++ b/modules/store/src/main/scala/sharry/store/records/RShare.scala @@ -1,11 +1,11 @@ package sharry.store.records -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RShare( id: Ident, diff --git a/modules/store/src/main/scala/sharry/store/records/RShareFile.scala b/modules/store/src/main/scala/sharry/store/records/RShareFile.scala index c7e73880..783964dc 100644 --- a/modules/store/src/main/scala/sharry/store/records/RShareFile.scala +++ b/modules/store/src/main/scala/sharry/store/records/RShareFile.scala @@ -1,11 +1,11 @@ package sharry.store.records -import sharry.common._ -import sharry.store.doobie.DoobieMeta._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* +import sharry.store.doobie.DoobieMeta.* -import doobie._ -import doobie.implicits._ +import doobie.* +import doobie.implicits.* case class RShareFile( id: Ident, diff --git a/modules/store/src/test/scala/sharry/store/PermanentErrorTest.scala b/modules/store/src/test/scala/sharry/store/PermanentErrorTest.scala index 428e6eaa..226aa428 100644 --- a/modules/store/src/test/scala/sharry/store/PermanentErrorTest.scala +++ b/modules/store/src/test/scala/sharry/store/PermanentErrorTest.scala @@ -1,6 +1,6 @@ package sharry.store -import munit._ +import munit.* class PermanentErrorTest extends FunSuite { val nativePart = "value for domain safe_bytea violates check constraint" diff --git a/modules/store/src/test/scala/sharry/store/StoreFixture.scala b/modules/store/src/test/scala/sharry/store/StoreFixture.scala index ec2698de..70968b52 100644 --- a/modules/store/src/test/scala/sharry/store/StoreFixture.scala +++ b/modules/store/src/test/scala/sharry/store/StoreFixture.scala @@ -4,14 +4,14 @@ import java.nio.file.Paths import scala.util.Random -import cats.effect._ +import cats.effect.* import cats.effect.unsafe.implicits.global import fs2.io.file.Files -import sharry.common._ -import sharry.store.doobie._ +import sharry.common.* +import sharry.store.doobie.* -import _root_.doobie._ +import _root_.doobie.* import org.h2.jdbcx.JdbcConnectionPool import scodec.bits.ByteVector From e78aafe888ba403cd2b639a97b341e2e813d98d3 Mon Sep 17 00:00:00 2001 From: eikek Date: Mon, 10 Jun 2024 23:45:14 +0200 Subject: [PATCH 07/10] Convert config to ciris --- .../main/scala/sharry/common/Duration.scala | 7 + .../src/main/resources/reference.conf | 14 +- .../main/scala/sharry/restserver/Main.scala | 2 +- .../restserver/config/ConfigDecoders.scala | 60 ++++- .../sharry/restserver/config/ConfigFile.scala | 58 +---- .../restserver/config/ConfigValues.scala | 231 +++++++++++++++--- .../scala/sharry/store/FileStoreType.scala | 3 +- 7 files changed, 275 insertions(+), 100 deletions(-) diff --git a/modules/common/src/main/scala/sharry/common/Duration.scala b/modules/common/src/main/scala/sharry/common/Duration.scala index 382a43ef..aaf55e74 100644 --- a/modules/common/src/main/scala/sharry/common/Duration.scala +++ b/modules/common/src/main/scala/sharry/common/Duration.scala @@ -63,6 +63,13 @@ object Duration { val zero: Duration = new Duration(0L) + def fromString(s: String): Either[String, Duration] = + s.toLongOption match + case Some(n) => Right(millis(n)) + case None => + try Right(apply(scala.concurrent.duration.Duration(s))) + catch case ex: Throwable => Left(s"Invalid duration '$s': ${ex.getMessage}") + def apply(d: SDur): Duration = new Duration(d.toNanos) diff --git a/modules/restserver/src/main/resources/reference.conf b/modules/restserver/src/main/resources/reference.conf index 383f044f..93211f57 100644 --- a/modules/restserver/src/main/resources/reference.conf +++ b/modules/restserver/src/main/resources/reference.conf @@ -390,7 +390,6 @@ sharry.restserver { # invitation key. Invitation keys can be generated by an admin. # - closed: signing up is disabled. mode = "open" - mode = ${?SHARRY_BACKEND_SIGNUP_MODE} # If mode == 'invite', this is the period an invitation token is # considered valid. @@ -401,7 +400,6 @@ sharry.restserver { # invitation keys. Generating such keys is only permitted to # admin users. invite-password = "generate-invite" - invite-password = ${?SHARRY_BACKEND_SIGNUP_INVITE__PASSWORD} } @@ -425,7 +423,7 @@ sharry.restserver { # # See issue https://github.com/eikek/sharry/issues/255 – the # example is a virus check via a postgresql extension "snakeoil". - database-domain-checks = [ + database-domain-checks = { # Example: This message originates from postgres with an # enabled snakeoil extension. This extension allows to virus # check byte arrays. It must be setup such that the `bytea` @@ -435,11 +433,12 @@ sharry.restserver { # CREATE EXTENSION pg_snakeoil; # CREATE DOMAIN public.safe_bytea as bytea CHECK (not so_is_infected(value)); # ALTER TABLE public.filechunk ALTER COLUMN chunkdata TYPE safe_bytea; - { enabled = false + snakeoil = { + enabled = false native = "domain safe_bytea violates check constraint" message = "The uploaded file contains a virus!" } - ] + } } cleanup { @@ -468,20 +467,15 @@ sharry.restserver { smtp { # Host and port of the SMTP server host = "localhost" - host = ${?SHARRY_BACKEND_MAIL_SMTP_HOST} port = 25 - port = ${?SHARRY_BACKEND_MAIL_SMTP_PORT} # User credentials to authenticate at the server. If the user # is empty, mails are sent without authentication. user = "" - user = ${?SHARRY_BACKEND_MAIL_SMTP_USER} password = "" - password = ${?SHARRY_BACKEND_MAIL_SMTP_PASSWORD} # One of: none, starttls, ssl ssl-type = "starttls" - ssl-type = ${?SHARRY_BACKEND_MAIL_SMTP_SSL__TYPE} # In case of self-signed certificates or other problems like # that, checking certificates can be disabled. diff --git a/modules/restserver/src/main/scala/sharry/restserver/Main.scala b/modules/restserver/src/main/scala/sharry/restserver/Main.scala index b51c67e8..67a594f6 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/Main.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/Main.scala @@ -60,7 +60,7 @@ object Main extends IOApp { } } - cfg = ConfigFile.loadConfig + cfg <- ConfigFile.loadConfig _ <- ScribeConfigure.configure[IO](cfg.logging) diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala index e8704590..3c9e19a0 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigDecoders.scala @@ -4,16 +4,21 @@ import scala.jdk.CollectionConverters.* import cats.Show import cats.syntax.all.* +import fs2.io.file.Path import sharry.common.* import sharry.logging.Level import sharry.logging.LogConfig +import sharry.store.FileStoreType import ciris.* import com.comcast.ip4s.{Host, Port} import com.typesafe.config.ConfigValue as TCValue +import emil.javamail.syntax.* +import emil.{MailAddress, SSLType} import org.http4s.Uri import scodec.bits.ByteVector +import yamusca.data.Template private[config] trait ConfigDecoders: extension [A, B](self: ConfigDecoder[A, B]) @@ -22,6 +27,14 @@ private[config] trait ConfigDecoders: f(b).left.map(err => ConfigError.decode(typeName, key, b)) ) + extension [A](self: ConfigValue[Effect, List[A]]) + def listflatMap[B](f: A => ConfigValue[Effect, B]): ConfigValue[Effect, List[B]] = + self.flatMap(ids => + ids.foldLeft(ConfigValue.loaded(ConfigKey(""), List.empty[B])) { (cv, id) => + cv.flatMap(l => f(id).map(_ :: l)) + } + ) + given ConfigDecoder[TCValue, String] = ConfigDecoder[TCValue].map(_.atKey("a").getString("a")) @@ -45,7 +58,7 @@ private[config] trait ConfigDecoders: val inner = cv.atKey("a").getConfig("a") inner.root.keySet.asScala.toList .traverse { key => - val value = inner.getObject(key) + val value = inner.getValue(s"\"$key\"") ConfigDecoder[String, K] .decode(cfgKey, key) .flatMap(k => @@ -55,11 +68,28 @@ private[config] trait ConfigDecoders: .map(_.toMap) } + given [A](using ConfigDecoder[String, A]): ConfigDecoder[String, List[A]] = + ConfigDecoder[String].mapEither { (ckey, str) => + str + .split(',') + .toList + .map(_.trim) + .filter(_.nonEmpty) + .traverse( + ConfigDecoder[String, A].decode(ckey, _) + ) + } + + given [A, B](using ConfigDecoder[A, B]): ConfigDecoder[List[A], List[B]] = + ConfigDecoder.instance { (ckey, lista) => + lista.traverse(ConfigDecoder[A, B].decode(ckey, _)) + } + given [A](using ConfigDecoder[String, A]): ConfigDecoder[TCValue, A] = ConfigDecoder[TCValue, String].as[A] given ConfigDecoder[String, Duration] = - ConfigDecoder[String].as[scala.concurrent.duration.Duration].map(Duration.apply) + ConfigDecoder[String].emap("Duration")(Duration.fromString) given ConfigDecoder[String, LenientUri] = ConfigDecoder[String].emap("LenientUri")(LenientUri.parse) @@ -96,3 +126,29 @@ private[config] trait ConfigDecoders: given ConfigDecoder[String, LogConfig.Format] = ConfigDecoder[String].emap("LogFormat")(LogConfig.Format.fromString) + + given ConfigDecoder[String, FileStoreType] = + ConfigDecoder[String].emap("FileStoreType")(FileStoreType.fromString) + + given ConfigDecoder[String, Path] = + ConfigDecoder[String].map(Path(_)) + + given ConfigDecoder[String, SignupMode] = + ConfigDecoder[String].emap("SignupMode")(SignupMode.fromString) + + given ConfigDecoder[String, SSLType] = + ConfigDecoder[String].emap("SSLType")(SSLType.fromString) + + given ConfigDecoder[String, MailAddress] = + ConfigDecoder[String].emap("MailAddress")(MailAddress.parse) + + given ConfigDecoder[String, Option[MailAddress]] = + ConfigDecoder[String].mapEither { (key, s) => + if (s.isEmpty) Right(None) + else ConfigDecoder[String, MailAddress].decode(key, s).map(Some(_)) + } + + given ConfigDecoder[String, Template] = + ConfigDecoder[String].emap("Template")(str => + yamusca.parser.parse(str).left.map(_._2) + ) diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala index f7bfdb27..7b74bdee 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigFile.scala @@ -1,62 +1,10 @@ package sharry.restserver.config -//import sharry.logging.{Level, LogConfig} -//import sharry.store.{FileStoreConfig, FileStoreType} - -// import emil.MailAddress -// import emil.SSLType -// import emil.javamail.syntax._ -// import yamusca.imports.{Template, mustache} +import cats.effect.* object ConfigFile { - // import Implicits._ - - def loadConfig: Config = ??? - // ConfigSource.default.at("sharry.restserver").loadOrThrow[Config].validOrThrow - - // object Implicits { - // implicit val mailAddressReader: ConfigReader[Option[MailAddress]] = - // ConfigReader[String].emap( - // reason(s => - // if (s.trim.isEmpty) Right(None) else MailAddress.parse(s).map(m => Some(m)) - // ) - // ) - - // implicit val mailSslTypeReader: ConfigReader[SSLType] = - // ConfigReader[String].emap( - // reason(s => - // s.toLowerCase match { - // case "none" => Right(SSLType.NoEncryption) - // case "starttls" => Right(SSLType.StartTLS) - // case "ssl" => Right(SSLType.SSL) - // case _ => Left(s"Invalid ssl type '$s'. Use one of none, ssl or starttls.") - // } - // ) - // ) - - // implicit val templateReader: ConfigReader[Template] = - // ConfigReader[String].emap( - // reason(s => - // mustache.parse(s).left.map(err => s"Error parsing template at ${err._1.pos}") - // ) - // ) - - // implicit val logFormatReader: ConfigReader[LogConfig.Format] = - // ConfigReader[String].emap(reason(LogConfig.Format.fromString)) - - // implicit val logLevelReader: ConfigReader[Level] = - // ConfigReader[String].emap(reason(Level.fromString)) - - // implicit val fileStoreTypeReader: ConfigReader[FileStoreType] = - // ConfigReader[String].emap(reason(FileStoreType.fromString)) + def loadConfig: IO[Config] = + ConfigValues.fullConfig.load[IO] - // // the value "s-3" looks strange, this is to allow to write "s3" in the config - // implicit val fileStoreCoproductHint: CoproductHint[FileStoreConfig] = - // new FieldCoproductHint[FileStoreConfig]("type") { - // override def fieldValue(name: String) = - // if (name.equalsIgnoreCase("S3")) "s3" - // else super.fieldValue(name) - // } - // } } diff --git a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala index 4101413d..2e08f1c0 100644 --- a/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala +++ b/modules/restserver/src/main/scala/sharry/restserver/config/ConfigValues.scala @@ -3,37 +3,73 @@ package sharry.restserver.config import scala.jdk.CollectionConverters.* import cats.syntax.all.* +import fs2.io.file.Path import sharry.backend.auth.AuthConfig +import sharry.backend.config.{Config as BackendConfig, CopyFilesConfig, FilesConfig} +import sharry.backend.job.CleanupConfig +import sharry.backend.mail.MailConfig +import sharry.backend.share.ShareConfig +import sharry.backend.signup.SignupConfig import sharry.common.* import sharry.logging.Level import sharry.logging.LogConfig +import sharry.store.ComputeChecksumConfig +import sharry.store.DomainCheckConfig +import sharry.store.FileStoreConfig +import sharry.store.FileStoreType import sharry.store.JdbcConfig import ciris.* import com.comcast.ip4s.{Host, Port} -import org.http4s.Uri +import emil.MailAddress +import emil.SSLType import scodec.bits.ByteVector +import yamusca.data.Template -@annotation.nowarn object ConfigValues extends ConfigDecoders: private val hocon = Hocon.at("sharry.restserver") private def senv(envName: String) = env(s"SHARRY_${envName}") private def key(hoconPath: String, envName: String) = - hocon(hoconPath).as[String].or(senv(envName)) + senv(envName).or(hocon(hoconPath).as[String]) private def keyMap[A, B](hoconPath: String, envName: String)(using ConfigDecoder[String, A], ConfigDecoder[String, B] - ) = - hocon(hoconPath).as[Map[A, B]] + ) = { + val envMap = senv(s"${envName}_NAMES") + .as[List[String]] + .listflatMap { k => + val value = senv(s"${envName}_$k").as[B] + val ckey = ConfigKey(s"${envName} key: $k") + val kk = ConfigDecoder[String, A] + .decode(Some(ckey), k) + .fold(ConfigValue.failed, ConfigValue.loaded(ckey, _)) + + value.flatMap(v => kk.map(_ -> v)) + } + .map(_.toMap) + + envMap.or(hocon(hoconPath).as[Map[A, B]]) + } private def keyList[A](hoconPath: String, envName: String)(using ConfigDecoder[String, A] ) = - hocon(hoconPath).as[List[A]] + senv(envName).as[List[A]].or(hocon(hoconPath).as[List[A]]) + + private def mapKeys[A](hoconPath: String, envName: String)(using + ConfigDecoder[String, A] + ) = { + val hoconKeys = + hocon(hoconPath) + .map(_.atKey("a").getConfig("a").root.keySet.asScala.toList) + .as[List[A]] + val envKeys = senv(envName).as[List[A]] + envKeys.or(hoconKeys) + } - val baseUrl = key("base-url", "BASE_URL").as[Uri] + val baseUrl = key("base-url", "BASE_URL").as[LenientUri] val bind = { val address = key("bind.address", "BIND_ADDRESS").as[Host] @@ -198,31 +234,8 @@ object ConfigValues extends ConfigDecoders: ).mapN(AuthConfig.OAuth.apply) } - val authOAuthKeys = { - def stringsToIds(strs: List[String]) = - strs.traverse(Ident.fromString) match - case Right(ids) => ConfigValue.loaded(ConfigKey(""), ids) - case Left(err) => ConfigValue.failed(ConfigError(err)) - - val hoconKeys = - hocon("backend.auth.oauth") - .map(_.atKey("a").getConfig("a").root.keySet.asScala.toList) - .flatMap(stringsToIds) - - val envKeys = - senv("BACKEND_AUTH_OAUTH_IDS") - .map(s => s.split(',').toList.map(_.trim)) - .flatMap(stringsToIds) - - hoconKeys.or(envKeys) - } - val authOAuthSeq = - authOAuthKeys.flatMap(ids => - ids.foldLeft(ConfigValue.loaded(ConfigKey(""), List.empty[AuthConfig.OAuth])) { - (cv, id) => cv.flatMap(l => authOAuth(id).map(_ :: l)) - } - ) + mapKeys[Ident]("backend.auth.oauth", "BACKEND_AUTH_OAUTH_IDS").listflatMap(authOAuth) val auth = { def k(p: String, e: String) = @@ -249,4 +262,160 @@ object ConfigValues extends ConfigDecoders: (url, user, pass).mapN(JdbcConfig.apply) } + def fileStoreConfig(id: String) = { + def k(p: String, e: String) = + key(s"backend.files.stores.$id.$p", s"BACKEND_FILES_STORES_${id.toUpperCase}_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + k("type", "TYPE").as[FileStoreType].flatMap { + case FileStoreType.DefaultDatabase => + enabled.map(FileStoreConfig.DefaultDatabase.apply) + + case FileStoreType.FileSystem => + val dir = k("directory", "DIRECTORY").as[Path] + val cleanDirs = k("clean-empty-dirs", "CLEAN_EMPTY_DIRS").as[Boolean] + (enabled, dir, cleanDirs).mapN(FileStoreConfig.FileSystem.apply) + + case FileStoreType.S3 => + val endpoint = k("endpoint", "ENDPOINT") + val accessKey = k("access-key", "ACCESS_KEY") + val secretKey = k("secret-key", "SECRET_KEY") + val bucket = k("bucket", "BUCKET") + (enabled, endpoint, accessKey, secretKey, bucket).mapN(FileStoreConfig.S3.apply) + } + } + + val copyFiles = { + def k(p: String, e: String) = + key(s"backend.files.copy-files.$p", s"BACKEND_FILES_COPY_FILES_$e") + + val enabled = k("enable", "ENABLE").as[Boolean] + val source = k("source", "SOURCE").as[Ident] + val target = k("target", "TARGET").as[Ident] + val parallel = k("parallel", "PARALLEL").as[Int] + (enabled, source, target, parallel).mapN(CopyFilesConfig.apply) + } + + val files = { + val defaultStore = + key("backend.files.default-store", "BACKEND_FILES_DEFAULT_STORE").as[Ident] + val stores = mapKeys[Ident]("backend.files.stores", "BACKEND_FILES_STORES_IDS") + .listflatMap(id => fileStoreConfig(id.id).map(id -> _)) + .map(_.toMap) + (defaultStore, stores, copyFiles).mapN(FilesConfig.apply) + } + + val computeChecksum = { + def k(p: String, e: String) = + key(s"backend.compute-checksum.$p", s"BACKEND_COMPUTE_CHECKSUM_$e") + + val enable = k("enable", "ENABLE").as[Boolean] + val capacity = k("capacity", "CAPACITY").as[Int] + val parallel = k("parallel", "PARALLEL").as[Int] + val useDefault = k("use-default", "USE_DEFAULT").as[Boolean] + (enable, capacity, parallel, useDefault).mapN(ComputeChecksumConfig.apply) + } + + val signup = { + def k(p: String, e: String) = + key(s"backend.signup.$p", s"BACKEND_SIGNUP_$e") + + val mode = k("mode", "MODE").as[SignupMode] + val inviteTime = k("invite-time", "INVITE_TIME").as[Duration] + val invitePass = k("invite-password", "INVITE_PASSWORD").as[Password] + (mode, inviteTime, invitePass).mapN(SignupConfig.apply) + } + + def domainCheck(id: String) = { + def k(p: String, e: String) = + key( + s"backend.share.database-domain-checks.$id.$p", + s"BACKEND_SHARE_DATABASE_DOMAIN_CHECKS_${id.toUpperCase}.$e" + ) + + val enabled = k("enabled", "ENABLED").as[Boolean] + val nativeM = k("native", "NATIVE") + val message = k("message", "MESSAGE") + (enabled, nativeM, message).mapN(DomainCheckConfig.apply) + } + + val share = { + def k(p: String, e: String) = + key(s"backend.share.$p", s"BACKEND_SHARE_$e") + + val chunkSize = k("chunk-size", "CHUNK_SIZE").as[ByteSize] + val maxSize = k("max-size", "MAX_SIZE").as[ByteSize] + val maxValid = k("max-validity", "MAX_VALIDITY").as[Duration] + val domainChecks = mapKeys[String]( + "backend.share.database-domain-checks", + "BACKEND_SHARE_DATABASE_DOMAIN_CHECKS_IDS" + ) + .listflatMap(domainCheck) + (chunkSize, maxSize, maxValid, domainChecks).mapN(ShareConfig.apply) + } + + val cleanup = { + def k(p: String, e: String) = + key(s"backend.cleanup.$p", s"BACKEND_CLEANUP_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val interval = k("interval", "INTERVAL").as[Duration] + val invalidAge = k("invalid-age", "INVALID_AGE").as[Duration] + (enabled, interval, invalidAge).mapN(CleanupConfig.apply) + } + + val mailSmtp = { + def k(p: String, e: String) = + key(s"backend.mail.smtp.$p", s"BACKEND_MAIL_SMTP_$e") + + val host = k("host", "HOST") + val port = k("port", "PORT").as[Int] + val user = k("user", "USER") + val pass = k("password", "PASSWORD").as[Password].redacted + val sslType = k("ssl-type", "SSL_TYPE").as[SSLType] + val checkCerts = + k("check-certificates", "CHECK_CERTIFICATES").as[Boolean].default(true) + val timeout = k("timeout", "TIMEOUT").as[Duration] + val defaultFrom = k("default-from", "DEFAULT_FROM").as[Option[MailAddress]] + val listId = k("list-id", "LIST_ID") + (host, port, user, pass, sslType, checkCerts, timeout, defaultFrom, listId).mapN( + MailConfig.Smtp.apply + ) + } + + def mailTemplate(id: String) = { + def k(p: String, e: String) = + key( + s"backend.mail.templates.$id.$p", + s"BACKEND_MAIL_TEMPLATES_${id.toUpperCase}_$e" + ) + + val subject = k("subject", "SUBJECT").as[Template] + val body = k("body", "BODY").as[Template] + (subject, body).mapN(MailConfig.MailTpl.apply) + } + + val mail = { + def k(p: String, e: String) = + key(s"backend.mail.$p", s"BACKEND_MAIL_$e") + + val enabled = k("enabled", "ENABLED").as[Boolean] + val downloadTpl = mailTemplate("download") + val aliasTpl = mailTemplate("alias") + val uploadTpl = mailTemplate("upload-notify") + val templates = (downloadTpl, aliasTpl, uploadTpl).mapN(MailConfig.Templates.apply) + (enabled, mailSmtp, templates).mapN(MailConfig.apply) + } + + val backendConfig = + (jdbc, signup, auth, share, cleanup, mail, files, computeChecksum).mapN( + BackendConfig.apply + ) + + val fullConfig = + (baseUrl, aliasMemberEnabled, bind, fileDownload, logConfig, webapp, backendConfig) + .mapN( + Config.apply + ) + end ConfigValues diff --git a/modules/store/src/main/scala/sharry/store/FileStoreType.scala b/modules/store/src/main/scala/sharry/store/FileStoreType.scala index 9976e4b9..e9204acb 100644 --- a/modules/store/src/main/scala/sharry/store/FileStoreType.scala +++ b/modules/store/src/main/scala/sharry/store/FileStoreType.scala @@ -17,8 +17,9 @@ object FileStoreType { NonEmptyList.of(DefaultDatabase, S3, FileSystem) def fromString(str: String): Either[String, FileStoreType] = + val sn = str.replaceAll("[-_]", "") // allow kebab- and snake-case all - .find(_.name.equalsIgnoreCase(str)) + .find(e => e.name.equalsIgnoreCase(sn) || e.name.equalsIgnoreCase(str)) .toRight(s"Invalid file store type: $str") def unsafeFromString(str: String): FileStoreType = From b57ad1bb80377e8695d2459323a6afc1869deaa4 Mon Sep 17 00:00:00 2001 From: eikek Date: Tue, 11 Jun 2024 20:32:30 +0200 Subject: [PATCH 08/10] Add a few words to the docs --- flake.nix | 4 +- modules/microsite/docs/doc/configure.md | 65 +++++++++++++++++-------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/flake.nix b/flake.nix index 5a0dc49e..d62936ab 100644 --- a/flake.nix +++ b/flake.nix @@ -72,7 +72,7 @@ SHARRY_BACKEND_MAIL_SMTP_PORT = "25"; SHARRY_BACKEND_MAIL_SMTP_USER = "admin"; SHARRY_BACKEND_MAIL_SMTP_PASSWORD = "admin"; - SHARRY_BACKEND_MAIL_SMTP_SSL__TYPE = "none"; + SHARRY_BACKEND_MAIL_SMTP_SSL_TYPE = "none"; }; dev-vm = pkgs.mkShellNoCC { @@ -91,7 +91,7 @@ SHARRY_BACKEND_MAIL_SMTP_PORT = "10025"; SHARRY_BACKEND_MAIL_SMTP_USER = "admin"; SHARRY_BACKEND_MAIL_SMTP_PASSWORD = "admin"; - SHARRY_BACKEND_MAIL_SMTP_SSL__TYPE = "none"; + SHARRY_BACKEND_MAIL_SMTP_SSL_TYPE = "none"; }; ci = pkgs.mkShellNoCC { buildInputs = ciPkgs; diff --git a/modules/microsite/docs/doc/configure.md b/modules/microsite/docs/doc/configure.md index c7a028fd..13d581a7 100644 --- a/modules/microsite/docs/doc/configure.md +++ b/modules/microsite/docs/doc/configure.md @@ -11,6 +11,14 @@ that is not given, the defaults are used. The config file overrides default values, so only values that differ from the defaults are necessary to specify. +Environment variables can be used as well to override values from the +config file. Variable names always start with `SHARRY_` and the +remainder can be derived from the corresponding config option by +replacing period `.` and dash `-` by an underscore `_`, but excluding +the root namespace `sharry.restserver`. For example, the config option +`sharry.restserver.bind.address` would be `SHARRY_BIND_ADDRESS` as +environment variable. A value given as environment variable has +priority. ## File Format @@ -23,6 +31,19 @@ allows comments and has some [advanced features](https://github.com/lightbend/config/blob/master/README.md#features-of-hocon). Please refer to their documentation for more on this. +The hocon format allows to include environment variables, allowing to +mix and match both variants if desired. For example: + +```conf +… + mode = "open" + mode = ${?SHARRY_BACKEND_SIGNUP_MODE} +… +``` + +would use the value `"open"` if the environment varible +`SHARRY_BACKEND_SIGNUP_MODE` is not defined, because it would +overwrite the previously defined value. ## Important Config Options @@ -97,7 +118,7 @@ sharry.restserver.backend.share { # # See issue https://github.com/eikek/sharry/issues/255 – the # example is a virus check via a postgresql extension "snakeoil". - database-domain-checks = [ + database-domain-checks = { # Example: This message originates from postgres with an # enabled snakeoil extension. This extension allows to virus # check byte arrays. It must be setup such that the `bytea` @@ -107,11 +128,12 @@ sharry.restserver.backend.share { # CREATE EXTENSION pg_snakeoil; # CREATE DOMAIN public.safe_bytea as bytea CHECK (not so_is_infected(value)); # ALTER TABLE public.filechunk ALTER COLUMN chunkdata TYPE safe_bytea; - { enabled = false + snakeoil = { + enabled = false native = "domain safe_bytea violates check constraint" message = "The uploaded file contains a virus!" } - ] + } } ``` @@ -479,24 +501,25 @@ The `oauth` login module can be configured with multiple such providers. Here is an example: ``` -oauth = [ - { - enabled = false - id = "github" - name = "Github" - icon = "fab fa-github" - authorize-url = "https://github.com/login/oauth/authorize" - token-url = "https://github.com/login/oauth/access_token" - user-url = "https://api.github.com/user" - user-id-key = "login" - scope = "" - client-id = "" - client-secret = "" - } -] -``` - -Each such entry in the array results in a button on the login screen. +oauth = { + github = { + enabled = false + name = "Github" + icon = "fab fa-github" + authorize-url = "https://github.com/login/oauth/authorize" + token-url = "https://github.com/login/oauth/access_token" + user-url = "https://api.github.com/user" + user-id-key = "login" + scope = "" + client-id = "" + client-secret = "" + } +} +``` + +Each such entry in the `oauth` object results in a button on the login +screen. The key (`github` in the above example) is used to refer to +this provider as its id. From 9d766a16e3c84a2013e2b3c0edefe4b23ac2c52c Mon Sep 17 00:00:00 2001 From: eikek Date: Tue, 11 Jun 2024 20:34:21 +0200 Subject: [PATCH 09/10] Remove comments --- build.sbt | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.sbt b/build.sbt index 9df6254e..cbfe2ce1 100644 --- a/build.sbt +++ b/build.sbt @@ -122,7 +122,6 @@ val loggingApi = project .settings(testSettingsMUnit) .settings( name := "sharry-logging-api", -// addCompilerPlugin(Dependencies.kindProjectorPlugin), libraryDependencies ++= Dependencies.circeCore ++ Dependencies.fs2 ++ @@ -149,7 +148,6 @@ val loggingScribe = project .settings(testSettingsMUnit) .settings( name := "sharry-logging-scribe", -// addCompilerPlugin(Dependencies.kindProjectorPlugin), libraryDependencies ++= Dependencies.scribe ++ Dependencies.circeCore ++ From b44470bd667798d71b98465f8e92bcf5411bb684 Mon Sep 17 00:00:00 2001 From: eikek Date: Tue, 11 Jun 2024 20:38:22 +0200 Subject: [PATCH 10/10] Remove pureconfig from dependencies --- project/Dependencies.scala | 7 ------- 1 file changed, 7 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 3b4f7692..335a5857 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -20,7 +20,6 @@ object Dependencies { val MUnitVersion = "1.0.0" val MUnitCatsEffectVersion = "2.0.0" val PostgresVersion = "42.7.3" - val PureConfigVersion = "0.17.7" val ScribeVersion = "3.15.0" val SourcecodeVersion = "0.4.2" val SwaggerVersion = "5.17.14" @@ -77,12 +76,6 @@ object Dependencies { "io.circe" %% "circe-parser" % CirceVersion ) - // https://github.com/melrief/pureconfig - // MPL 2.0 - val pureconfig = Seq( - "com.github.pureconfig" %% "pureconfig-core" % PureConfigVersion - ) - // https://github.com/h2database/h2database // MPL 2.0 or EPL 1.0 val h2 = Seq(