Get item details from a share

This commit is contained in:
eikek 2021-10-06 09:36:38 +02:00
parent c62b8526be
commit 1a10216e3d
5 changed files with 153 additions and 6 deletions

View File

@ -17,6 +17,7 @@ import docspell.backend.ops.OShare.{ShareQuery, VerifyResult}
import docspell.backend.ops.OSimpleSearch.StringSearchResult
import docspell.common._
import docspell.query.ItemQuery
import docspell.query.ItemQuery.Expr
import docspell.query.ItemQuery.Expr.AttachId
import docspell.store.Store
import docspell.store.queries.SearchSummary
@ -57,6 +58,8 @@ trait OShare[F[_]] {
def findAttachment(attachId: Ident, shareId: Ident): OptionT[F, AttachmentData[F]]
def findItem(itemId: Ident, shareId: Ident): OptionT[F, ItemData]
def searchSummary(
settings: OSimpleSearch.StatsSettings
)(shareId: Ident, q: ItemQueryString): OptionT[F, StringSearchResult[SearchSummary]]
@ -234,24 +237,31 @@ object OShare {
): OptionT[F, AttachmentPreviewData[F]] =
for {
sq <- findShareQuery(shareId)
_ <- checkAttachment(sq, attachId)
_ <- checkAttachment(sq, AttachId(attachId.id))
res <- OptionT(itemSearch.findAttachmentPreview(attachId, sq.cid))
} yield res
def findAttachment(attachId: Ident, shareId: Ident): OptionT[F, AttachmentData[F]] =
for {
sq <- findShareQuery(shareId)
_ <- checkAttachment(sq, attachId)
_ <- checkAttachment(sq, AttachId(attachId.id))
res <- OptionT(itemSearch.findAttachment(attachId, sq.cid))
} yield res
def findItem(itemId: Ident, shareId: Ident): OptionT[F, ItemData] =
for {
sq <- findShareQuery(shareId)
_ <- checkAttachment(sq, Expr.itemIdEq(itemId.id))
res <- OptionT(itemSearch.findItem(itemId, sq.cid))
} yield res
/** Check whether the attachment with the given id is in the results of the given
* share
*/
private def checkAttachment(sq: ShareQuery, attachId: Ident): OptionT[F, Unit] = {
private def checkAttachment(sq: ShareQuery, idExpr: Expr): OptionT[F, Unit] = {
val checkQuery = Query(
Query.Fix(sq.asAccount, Some(sq.query.expr), None),
Query.QueryExpr(AttachId(attachId.id))
Query.QueryExpr(idExpr)
)
OptionT(
itemSearch
@ -259,7 +269,7 @@ object OShare {
.map(_.headOption.map(_ => ()))
).flatTapNone(
logger.info(
s"Attempt to load unshared attachment '${attachId.id}' via share: ${sq.id.id}"
s"Attempt to load unshared data '$idExpr' via share: ${sq.id.id}"
)
)
}

View File

@ -188,6 +188,10 @@ object ItemQuery {
def date(op: Operator, attr: DateAttr, value: Date): SimpleExpr =
SimpleExpr(op, Property(attr, value))
def itemIdEq(itemId1: String, moreIds: String*): Expr =
if (moreIds.isEmpty) string(Operator.Eq, Attr.ItemId, itemId1)
else InExpr(Attr.ItemId, Nel(itemId1, moreIds.toList))
}
}

View File

@ -1603,6 +1603,97 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/SearchStats"
/share/item/{id}:
get:
operationId: "share-item-get"
tags: [ Share ]
summary: Get details about an item.
description: |
Get detailed information about an item.
security:
- shareTokenHeader: []
parameters:
- $ref: "#/components/parameters/id"
responses:
200:
description: Ok
content:
application/json:
schema:
$ref: "#/components/schemas/ItemDetail"
/share/attachment/{id}:
head:
operationId: "share-attach-head"
tags: [ Share ]
summary: Get headers to an attachment file.
description: |
Get information about the binary file belonging to the
attachment with the given id.
security:
- shareTokenHeader: []
parameters:
- $ref: "#/components/parameters/id"
responses:
200:
description: Ok
headers:
Content-Type:
schema:
type: string
Content-Length:
schema:
type: integer
format: int64
ETag:
schema:
type: string
Content-Disposition:
schema:
type: string
get:
operationId: "share-attach-get"
tags: [ Share ]
summary: Get an attachment file.
description: |
Get the binary file belonging to the attachment with the given
id. The binary is a pdf file. If conversion failed, then the
original file is returned.
security:
- shareTokenHeader: []
parameters:
- $ref: "#/components/parameters/id"
responses:
200:
description: Ok
content:
application/octet-stream:
schema:
type: string
format: binary
/share/attachment/{id}/view:
get:
operationId: "share-attach-show-viewerjs"
tags: [ Share ]
summary: A javascript rendered view of the pdf attachment
description: |
This provides a preview of the attachment rendered in a
browser.
It currently uses a third-party javascript library (viewerjs)
to display the preview. This works by redirecting to the
viewerjs url with the attachment url as parameter. Note that
the resulting url that is redirected to is not stable. It may
change from version to version. This route, however, is meant
to provide a stable url for the preview.
security:
- shareTokenHeader: []
parameters:
- $ref: "#/components/parameters/id"
responses:
303:
description: See Other
200:
description: Ok
/share/attachment/{id}/preview:
head:
operationId: "share-attach-check-preview"

View File

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

View File

@ -0,0 +1,41 @@
/*
* 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.restapi.model.BasicResult
import docspell.restserver.conv.Conversions
import org.http4s._
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.dsl.Http4sDsl
object ShareItemRoutes {
def apply[F[_]: Async](
backend: BackendApp[F],
token: ShareToken
): HttpRoutes[F] = {
val dsl = new Http4sDsl[F] {}
import dsl._
HttpRoutes.of { case GET -> Root / Ident(id) =>
for {
item <- backend.share.findItem(id, token.id).value
result = item.map(Conversions.mkItemDetail)
resp <-
result
.map(r => Ok(r))
.getOrElse(NotFound(BasicResult(false, "Not found.")))
} yield resp
}
}
}