mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Implement share preview image
This commit is contained in:
@ -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] = {
|
||||
|
@ -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]] = {
|
||||
|
@ -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" =>
|
||||
|
@ -452,7 +452,7 @@ object ItemRoutes {
|
||||
}
|
||||
}
|
||||
|
||||
private def searchItemStats[F[_]: Sync](
|
||||
def searchItemStats[F[_]: Sync](
|
||||
backend: BackendApp[F],
|
||||
dsl: Http4sDsl[F]
|
||||
)(
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
Reference in New Issue
Block a user