Update dependencies

This commit is contained in:
Eike Kettner 2019-12-28 12:38:11 +01:00
parent 07a23b9611
commit a9e70401de
6 changed files with 92 additions and 71 deletions

View File

@ -8,51 +8,78 @@ import cats.data.NonEmptyList
import cats.effect.{Blocker, ContextShift, Sync} import cats.effect.{Blocker, ContextShift, Sync}
import docspell.common.LenientUri.Path import docspell.common.LenientUri.Path
import io.circe.{Decoder, Encoder} import io.circe.{Decoder, Encoder}
import java.net.URLEncoder
import scodec.bits.ByteVector import scodec.bits.ByteVector
import cats.effect.Resource
import java.net.HttpURLConnection
/** A URI. /** A URI.
* *
* It is not compliant to rfc3986, but covers most use cases in a convenient way. * It is not compliant to rfc3986, but covers most use cases in a convenient way.
*/ */
case class LenientUri(scheme: NonEmptyList[String] case class LenientUri(
, authority: Option[String] scheme: NonEmptyList[String],
, path: LenientUri.Path authority: Option[String],
, query: Option[String] path: LenientUri.Path,
, fragment: Option[String]) { query: Option[String],
fragment: Option[String]
) {
def /(segment: String): LenientUri = def /(segment: String): LenientUri =
copy(path = path / segment) copy(path = path / segment)
def ++ (np: Path): LenientUri = def ++(np: Path): LenientUri =
copy(path = np.segments.foldLeft(path)(_ / _)) copy(path = np.segments.foldLeft(path)(_ / _))
def ++ (np: String): LenientUri = { def ++(np: String): LenientUri = {
val rel = LenientUri.stripLeading(np, '/') val rel = LenientUri.stripLeading(np, '/')
++(LenientUri.unsafe(s"a:$rel").path) ++(LenientUri.unsafe(s"a:$rel").path)
} }
def withQuery(name: String, value: String): LenientUri =
withQueryPlain(name, URLEncoder.encode(value, "UTF-8"))
def withQueryPlain(name: String, value: String): LenientUri =
copy(query = query.map(q => q + "&" + name + "=" + value).orElse(Option(s"$name=$value")))
def withFragment(f: String): LenientUri =
copy(fragment = Some(f))
def toJavaUrl: Either[String, URL] = def toJavaUrl: Either[String, URL] =
Either.catchNonFatal(new URL(asString)).left.map(_.getMessage) Either.catchNonFatal(new URL(asString)).left.map(_.getMessage)
def readURL[F[_]: Sync : ContextShift](chunkSize: Int, blocker: Blocker): Stream[F, Byte] = def open[F[_]: Sync]: Either[String, Resource[F, HttpURLConnection]] =
Stream.emit(Either.catchNonFatal(new URL(asString))). toJavaUrl.map { url =>
covary[F]. Resource
rethrow. .make(Sync[F].delay(url.openConnection().asInstanceOf[HttpURLConnection]))(
flatMap(url => fs2.io.readInputStream(Sync[F].delay(url.openStream()), chunkSize, blocker, true)) conn => Sync[F].delay(conn.disconnect())
)
}
def readURL[F[_]: Sync: ContextShift](chunkSize: Int, blocker: Blocker): Stream[F, Byte] =
Stream
.emit(Either.catchNonFatal(new URL(asString)))
.covary[F]
.rethrow
.flatMap(
url => fs2.io.readInputStream(Sync[F].delay(url.openStream()), chunkSize, blocker, true)
)
def host: Option[String] = def host: Option[String] =
authority. authority.map(
map(a => a.indexOf(':') match { a =>
case -1 => a a.indexOf(':') match {
case n => a.substring(0, n) case -1 => a
}) case n => a.substring(0, n)
}
)
def asString: String = { def asString: String = {
val schemePart = scheme.toList.mkString(":") val schemePart = scheme.toList.mkString(":")
val authPart = authority.map(a => s"//$a").getOrElse("") val authPart = authority.map(a => s"//$a").getOrElse("")
val pathPart = path.asString val pathPart = path.asString
val queryPart = query.map(q => s"?$q").getOrElse("") val queryPart = query.map(q => s"?$q").getOrElse("")
val fragPart = fragment.map(f => s"#$f").getOrElse("") val fragPart = fragment.map(f => s"#$f").getOrElse("")
s"$schemePart:$authPart$pathPart$queryPart$fragPart" s"$schemePart:$authPart$pathPart$queryPart$fragPart"
} }
} }
@ -68,30 +95,30 @@ object LenientUri {
} }
case object RootPath extends Path { case object RootPath extends Path {
val segments = Nil val segments = Nil
val isRoot = true val isRoot = true
val isEmpty = false val isEmpty = false
def /(seg: String): Path = def /(seg: String): Path =
NonEmptyPath(NonEmptyList.of(seg)) NonEmptyPath(NonEmptyList.of(seg))
def asString = "/" def asString = "/"
} }
case object EmptyPath extends Path { case object EmptyPath extends Path {
val segments = Nil val segments = Nil
val isRoot = false val isRoot = false
val isEmpty = true val isEmpty = true
def /(seg: String): Path = def /(seg: String): Path =
NonEmptyPath(NonEmptyList.of(seg)) NonEmptyPath(NonEmptyList.of(seg))
def asString = "" def asString = ""
} }
case class NonEmptyPath(segs: NonEmptyList[String]) extends Path { case class NonEmptyPath(segs: NonEmptyList[String]) extends Path {
def segments = segs.toList def segments = segs.toList
val isEmpty = false val isEmpty = false
val isRoot = false val isRoot = false
def /(seg: String): Path = def /(seg: String): Path =
copy(segs = segs.append(seg)) copy(segs = segs.append(seg))
def asString = segs.head match { def asString = segs.head match {
case "." => segments.map(percentEncode).mkString("/") case "." => segments.map(percentEncode).mkString("/")
case ".." => segments.map(percentEncode).mkString("/") case ".." => segments.map(percentEncode).mkString("/")
case _ => "/" + segments.map(percentEncode).mkString("/") case _ => "/" + segments.map(percentEncode).mkString("/")
} }
} }
@ -104,11 +131,12 @@ object LenientUri {
def parse(str: String): Either[String, LenientUri] = { def parse(str: String): Either[String, LenientUri] = {
def makePath(str: String): Path = str.trim match { def makePath(str: String): Path = str.trim match {
case "/" => RootPath case "/" => RootPath
case "" => EmptyPath case "" => EmptyPath
case _ => NonEmptyList.fromList(stripLeading(str, '/').split('/').toList.map(percentDecode)) match { case _ =>
case Some(nl) => NonEmptyPath(nl) NonEmptyList.fromList(stripLeading(str, '/').split('/').toList.map(percentDecode)) match {
case None => sys.error(s"Invalid url: $str") case Some(nl) => NonEmptyPath(nl)
} case None => sys.error(s"Invalid url: $str")
}
} }
def makeNonEmpty(str: String): Option[String] = def makeNonEmpty(str: String): Option[String] =
@ -128,9 +156,13 @@ object LenientUri {
case n => case n =>
pqf.indexOf('#', n) match { pqf.indexOf('#', n) match {
case -1 => case -1 =>
(makePath(pqf.substring(0, n)), makeNonEmpty(pqf.substring(n+1)), None) (makePath(pqf.substring(0, n)), makeNonEmpty(pqf.substring(n + 1)), None)
case k => case k =>
(makePath(pqf.substring(0, n)), makeNonEmpty(pqf.substring(n+1, k)), makeNonEmpty(pqf.substring(k+1))) (
makePath(pqf.substring(0, n)),
makeNonEmpty(pqf.substring(n + 1, k)),
makeNonEmpty(pqf.substring(k + 1))
)
} }
} }
@ -140,7 +172,7 @@ object LenientUri {
val scheme = makeScheme(p0) val scheme = makeScheme(p0)
val (auth, pathQF) = p1.indexOf('/') match { val (auth, pathQF) = p1.indexOf('/') match {
case -1 => (Some(p1), "") case -1 => (Some(p1), "")
case n => (Some(p1.substring(0, n)), p1.substring(n)) case n => (Some(p1.substring(0, n)), p1.substring(n))
} }
val (path, query, frag) = splitPathQF(pathQF) val (path, query, frag) = splitPathQF(pathQF)
scheme match { scheme match {
@ -155,7 +187,7 @@ object LenientUri {
case -1 => case -1 =>
Left(s"No scheme found: $str") Left(s"No scheme found: $str")
case n => case n =>
val scheme = makeScheme(p0.substring(0, n)) val scheme = makeScheme(p0.substring(0, n))
val (path, query, frag) = splitPathQF(p0.substring(n + 1)) val (path, query, frag) = splitPathQF(p0.substring(n + 1))
scheme match { scheme match {
case None => case None =>
@ -167,16 +199,13 @@ object LenientUri {
} }
} }
private[this] val delims: Set[Char] = ",/?:@&=+$# %".toSet private[this] val delims: Set[Char] = ",/?:@&$# %".toSet
private def percent(s: String): String = private def percent(s: String): String =
"%" + ByteVector.encodeUtf8(s). "%" + ByteVector.encodeUtf8(s).fold(throw _, identity).toHex
fold(throw _, identity).
toHex
def percentEncode(s: String): String = def percentEncode(s: String): String =
s.flatMap(c => s.flatMap(c => if (delims.contains(c)) percent(c.toString) else c.toString)
if (delims.contains(c)) percent(c.toString) else c.toString)
def percentDecode(s: String): String = def percentDecode(s: String): String =
if (!s.contains("%")) s if (!s.contains("%")) s
@ -188,13 +217,14 @@ object LenientUri {
else if (c == '%') ("%", res) else if (c == '%') ("%", res)
else (acc, res :+ c.toByte) else (acc, res :+ c.toByte)
} }
._2.decodeUtf8.fold(throw _, identity) ._2
.decodeUtf8
.fold(throw _, identity)
private def stripLeading(s: String, c: Char): String = private def stripLeading(s: String, c: Char): String =
if (s.length > 0 && s.charAt(0) == c) s.substring(1) if (s.length > 0 && s.charAt(0) == c) s.substring(1)
else s else s
implicit val encodeLenientUri: Encoder[LenientUri] = implicit val encodeLenientUri: Encoder[LenientUri] =
Encoder.encodeString.contramap(_.asString) Encoder.encodeString.contramap(_.asString)

View File

@ -26,7 +26,7 @@ object Authenticate {
val authUser = getUser[F](S.loginSession(cfg)) val authUser = getUser[F](S.loginSession(cfg))
val onFailure: AuthedRoutes[String, F] = val onFailure: AuthedRoutes[String, F] =
Kleisli(req => OptionT.liftF(Forbidden(req.authInfo))) Kleisli(req => OptionT.liftF(Forbidden(req.context)))
val middleware: AuthMiddleware[F, AuthToken] = val middleware: AuthMiddleware[F, AuthToken] =
AuthMiddleware(authUser, onFailure) AuthMiddleware(authUser, onFailure)
@ -41,12 +41,12 @@ object Authenticate {
val authUser = getUser[F](S.loginSession(cfg)) val authUser = getUser[F](S.loginSession(cfg))
val onFailure: AuthedRoutes[String, F] = val onFailure: AuthedRoutes[String, F] =
Kleisli(req => OptionT.liftF(Forbidden(req.authInfo))) Kleisli(req => OptionT.liftF(Forbidden(req.context)))
val middleware: AuthMiddleware[F, AuthToken] = val middleware: AuthMiddleware[F, AuthToken] =
AuthMiddleware(authUser, onFailure) AuthMiddleware(authUser, onFailure)
middleware(AuthedRoutes(authReq => f(authReq.authInfo).run(authReq.req))) middleware(AuthedRoutes(authReq => f(authReq.context).run(authReq.req)))
} }
private def getUser[F[_]: Effect](auth: String => F[Login.Result]): Kleisli[F, Request[F], Either[String, AuthToken]] = private def getUser[F[_]: Effect](auth: String => F[Login.Result]): Kleisli[F, Request[F], Either[String, AuthToken]] =

View File

@ -1,4 +1,3 @@
CREATE TABLE "filemeta" ( CREATE TABLE "filemeta" (
"id" varchar(254) not null primary key, "id" varchar(254) not null primary key,
"timestamp" varchar(40) not null, "timestamp" varchar(40) not null,

View File

@ -6,26 +6,24 @@ object Dependencies {
val BcryptVersion = "0.4" val BcryptVersion = "0.4"
val BetterMonadicForVersion = "0.3.1" val BetterMonadicForVersion = "0.3.1"
val BitpeaceVersion = "0.4.0" val BitpeaceVersion = "0.4.1"
val CirceVersion = "0.12.3" val CirceVersion = "0.12.3"
val DoobieVersion = "0.8.6" val DoobieVersion = "0.8.7"
val FastparseVersion = "2.1.3" val FastparseVersion = "2.1.3"
val FlywayVersion = "6.0.8" val FlywayVersion = "6.1.3"
val Fs2Version = "2.1.0" val Fs2Version = "2.1.0"
val H2Version = "1.4.200" val H2Version = "1.4.200"
val Http4sVersion = "0.21.0-M5" val Http4sVersion = "0.21.0-M6"
val KindProjectorVersion = "0.10.3" val KindProjectorVersion = "0.10.3"
val Log4sVersion = "1.8.2" val Log4sVersion = "1.8.2"
val LogbackVersion = "1.2.3" val LogbackVersion = "1.2.3"
val MariaDbVersion = "2.5.1" val MariaDbVersion = "2.5.2"
val MiniTestVersion = "2.7.0" val MiniTestVersion = "2.7.0"
val PostgresVersion = "42.2.8" val PostgresVersion = "42.2.9"
val PureConfigVersion = "0.12.1" val PureConfigVersion = "0.12.2"
val SqliteVersion = "3.28.0" val SqliteVersion = "3.30.1"
val StanfordNlpVersion = "3.9.2" val StanfordNlpVersion = "3.9.2"
val TikaVersion = "1.22" val TikaVersion = "1.23"
val javaxMailVersion = "1.6.2"
val dnsJavaVersion = "2.1.9"
val YamuscaVersion = "0.6.1" val YamuscaVersion = "0.6.1"
val stanfordNlpCore = Seq( val stanfordNlpCore = Seq(
@ -130,12 +128,6 @@ object Dependencies {
"org.flywaydb" % "flyway-core" % FlywayVersion "org.flywaydb" % "flyway-core" % FlywayVersion
) )
val javaxMail = Seq(
"javax.mail" % "javax.mail-api" % javaxMailVersion,
"com.sun.mail" % "javax.mail" % javaxMailVersion,
"dnsjava" % "dnsjava" % dnsJavaVersion intransitive()
)
val yamusca = Seq( val yamusca = Seq(
"com.github.eikek" %% "yamusca-core" % YamuscaVersion "com.github.eikek" %% "yamusca-core" % YamuscaVersion
) )
@ -151,7 +143,7 @@ object Dependencies {
val betterMonadicFor = "com.olegpy" %% "better-monadic-for" % BetterMonadicForVersion val betterMonadicFor = "com.olegpy" %% "better-monadic-for" % BetterMonadicForVersion
val webjars = Seq( val webjars = Seq(
"swagger-ui" -> "3.24.0", "swagger-ui" -> "3.24.3",
"Semantic-UI" -> "2.4.1", "Semantic-UI" -> "2.4.1",
"jquery" -> "3.4.1" "jquery" -> "3.4.1"
).map({case (a, v) => "org.webjars" % a % v }) ).map({case (a, v) => "org.webjars" % a % v })

View File

@ -1 +1 @@
sbt.version=1.3.3 sbt.version=1.3.6

View File

@ -2,6 +2,6 @@ addSbtPlugin("com.github.eikek" % "sbt-openapi-schema" % "0.5.0")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0") addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0")
addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.4.1") addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.5.2")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1-M3") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")
addSbtPlugin("com.47deg" % "sbt-microsites" % "0.9.2") addSbtPlugin("com.47deg" % "sbt-microsites" % "0.9.2")