Implement share preview image

This commit is contained in:
eikek
2021-10-05 09:24:11 +02:00
parent 7b0f378558
commit e52271f9cd
8 changed files with 115 additions and 27 deletions

View File

@ -142,7 +142,8 @@ object RestServer {
token: ShareToken
): HttpRoutes[F] =
Router(
"search" -> ShareSearchRoutes(restApp.backend, cfg, token)
"search" -> ShareSearchRoutes(restApp.backend, cfg, token),
"attachment" -> ShareAttachmentRoutes(restApp.backend, token)
)
def redirectTo[F[_]: Async](path: String): HttpRoutes[F] = {

View File

@ -10,19 +10,49 @@ import cats.data.NonEmptyList
import cats.data.OptionT
import cats.effect._
import cats.implicits._
import docspell.backend.ops.OItemSearch.AttachmentPreviewData
import docspell.backend.ops._
import docspell.restapi.model.BasicResult
import docspell.store.records.RFileMeta
import docspell.restserver.http4s.{QueryParam => QP}
import org.http4s._
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.dsl.Http4sDsl
import org.http4s.headers.ETag.EntityTag
import org.http4s.headers._
import org.http4s.headers.ETag.EntityTag
import org.typelevel.ci.CIString
object BinaryUtil {
def respond[F[_]: Async](dsl: Http4sDsl[F], req: Request[F])(
fileData: Option[AttachmentPreviewData[F]]
): F[Response[F]] = {
import dsl._
def notFound =
NotFound(BasicResult(false, "Not found"))
QP.WithFallback.unapply(req.multiParams) match {
case Some(bool) =>
val fallback = bool.getOrElse(false)
val inm = req.headers.get[`If-None-Match`].flatMap(_.tags)
val matches = matchETag(fileData.map(_.meta), inm)
fileData
.map { data =>
if (matches) withResponseHeaders(dsl, NotModified())(data)
else makeByteResp(dsl)(data)
}
.getOrElse(
if (fallback) BinaryUtil.noPreview(req.some).getOrElseF(notFound)
else notFound
)
case None =>
BadRequest(BasicResult(false, "Invalid query parameter 'withFallback'"))
}
}
def withResponseHeaders[F[_]: Sync](dsl: Http4sDsl[F], resp: F[Response[F]])(
data: OItemSearch.BinaryData[F]
): F[Response[F]] = {

View File

@ -17,7 +17,6 @@ import docspell.common.MakePreviewArgs
import docspell.restapi.model._
import docspell.restserver.conv.Conversions
import docspell.restserver.http4s.BinaryUtil
import docspell.restserver.http4s.{QueryParam => QP}
import docspell.restserver.webapp.Webjars
import org.http4s._
@ -115,25 +114,11 @@ object AttachmentRoutes {
.getOrElse(NotFound(BasicResult(false, "Not found")))
} yield resp
case req @ GET -> Root / Ident(id) / "preview" :? QP.WithFallback(flag) =>
def notFound =
NotFound(BasicResult(false, "Not found"))
case req @ GET -> Root / Ident(id) / "preview" =>
for {
fileData <-
backend.itemSearch.findAttachmentPreview(id, user.account.collective)
inm = req.headers.get[`If-None-Match`].flatMap(_.tags)
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
fallback = flag.getOrElse(false)
resp <-
fileData
.map { data =>
if (matches) withResponseHeaders(NotModified())(data)
else makeByteResp(data)
}
.getOrElse(
if (fallback) BinaryUtil.noPreview(req.some).getOrElseF(notFound)
else notFound
)
resp <- BinaryUtil.respond(dsl, req)(fileData)
} yield resp
case HEAD -> Root / Ident(id) / "preview" =>

View File

@ -452,7 +452,7 @@ object ItemRoutes {
}
}
private def searchItemStats[F[_]: Sync](
def searchItemStats[F[_]: Sync](
backend: BackendApp[F],
dsl: Http4sDsl[F]
)(

View File

@ -0,0 +1,37 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package docspell.restserver.routes
import cats.effect._
import cats.implicits._
import docspell.backend.BackendApp
import docspell.backend.auth.ShareToken
import docspell.common._
import docspell.restserver.http4s.BinaryUtil
import org.http4s.HttpRoutes
import org.http4s.dsl.Http4sDsl
object ShareAttachmentRoutes {
def apply[F[_]: Async](
backend: BackendApp[F],
token: ShareToken
): HttpRoutes[F] = {
val dsl = new Http4sDsl[F] {}
import dsl._
HttpRoutes.of { case req @ GET -> Root / Ident(id) / "preview" =>
for {
fileData <-
backend.share.findAttachmentPreview(id, token.id).value
resp <- BinaryUtil.respond(dsl, req)(fileData)
} yield resp
}
}
}

View File

@ -54,7 +54,7 @@ object ShareSearchRoutes {
cfg.maxNoteLength,
searchMode = SearchMode.Normal
)
account = AccountId(share.cid, Ident.unsafe(""))
account = share.asAccount
fixQuery = Query.Fix(account, Some(share.query.expr), None)
_ <- logger.debug(s"Searching in share ${share.id.id}: ${userQuery.query}")
resp <- ItemRoutes.searchItems(backend, dsl)(settings, fixQuery, itemQuery)