Implemented endpoint to delete multiple attachments

This commit is contained in:
Stefan Scheidewig 2021-04-15 18:05:01 +02:00
parent 93f772351a
commit fa34312020
4 changed files with 77 additions and 13 deletions

View File

@ -1,19 +1,15 @@
package docspell.backend.ops
import cats.data.NonEmptyList
import cats.data.OptionT
import cats.data.{NonEmptyList, OptionT}
import cats.effect.{Effect, Resource}
import cats.implicits._
import docspell.backend.JobFactory
import docspell.common._
import docspell.ftsclient.FtsClient
import docspell.store.UpdateResult
import docspell.store.queries.{QAttachment, QItem, QMoveAttachment}
import docspell.store.queue.JobQueue
import docspell.store.records._
import docspell.store.{AddResult, Store}
import docspell.store.{AddResult, Store, UpdateResult}
import doobie.implicits._
import org.log4s.getLogger
@ -140,6 +136,11 @@ trait OItem[F[_]] {
def deleteAttachment(id: Ident, collective: Ident): F[Int]
def deleteAttachmentMultiple(
attachments: NonEmptyList[Ident],
collective: Ident
): F[Int]
def moveAttachmentBefore(itemId: Ident, source: Ident, target: Ident): F[AddResult]
def setAttachmentName(
@ -602,6 +603,20 @@ object OItem {
.deleteSingleAttachment(store)(id, collective)
.flatTap(_ => fts.removeAttachment(logger, id))
def deleteAttachmentMultiple(
attachments: NonEmptyList[Ident],
collective: Ident
): F[Int] =
for {
attachmentIds <- store.transact(
RAttachment.filterAttachments(attachments, collective)
)
results <- attachmentIds.traverse(attachment =>
deleteAttachment(attachment, collective)
)
n = results.sum
} yield n
def setAttachmentName(
attachId: Ident,
name: Option[String],

View File

@ -80,6 +80,7 @@ object RestServer {
"item" -> ItemRoutes(cfg, pools.blocker, restApp.backend, token),
"items" -> ItemMultiRoutes(restApp.backend, token),
"attachment" -> AttachmentRoutes(pools.blocker, restApp.backend, token),
"attachments" -> AttachmentMultiRoutes(restApp.backend, token),
"upload" -> UploadRoutes.secured(restApp.backend, cfg, token),
"checkfile" -> CheckFileRoutes.secured(restApp.backend, token),
"email/send" -> MailSendRoutes(restApp.backend, token),

View File

@ -0,0 +1,38 @@
package docspell.restserver.routes
import cats.effect.Effect
import cats.implicits._
import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken
import docspell.restapi.model._
import docspell.restserver.conv.MultiIdSupport
import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._
import org.http4s.dsl.Http4sDsl
object AttachmentMultiRoutes extends MultiIdSupport {
def apply[F[_]: Effect](
backend: BackendApp[F],
user: AuthToken
): HttpRoutes[F] = {
val dsl = new Http4sDsl[F] {}
import dsl._
HttpRoutes.of { case req @ POST -> Root / "delete" =>
for {
json <- req.as[IdList]
attachments <- readIds[F](json.ids)
n <- backend.item.deleteAttachmentMultiple(attachments, user.account.collective)
res = BasicResult(
n > 0,
if (n > 0) "Attachment(s) deleted" else "Attachment deletion failed."
)
resp <- Ok(res)
} yield resp
}
}
}

View File

@ -1,16 +1,14 @@
package docspell.store.records
import bitpeace.FileMeta
import cats.data.NonEmptyList
import cats.implicits._
import fs2.Stream
import docspell.common._
import docspell.store.qb.DSL._
import docspell.store.qb._
import bitpeace.FileMeta
import doobie._
import doobie.implicits._
import fs2.Stream
case class RAttachment(
id: Ident,
@ -98,7 +96,6 @@ object RAttachment {
run(select(T.all), from(T), T.id === attachId).query[RAttachment].option
def findMeta(attachId: Ident): ConnectionIO[Option[FileMeta]] = {
import bitpeace.sql._
val m = RFileMeta.as("m")
val a = RAttachment.as("a")
@ -191,7 +188,6 @@ object RAttachment {
id: Ident,
coll: Ident
): ConnectionIO[Vector[(RAttachment, FileMeta)]] = {
import bitpeace.sql._
val a = RAttachment.as("a")
val m = RFileMeta.as("m")
@ -206,7 +202,6 @@ object RAttachment {
}
def findByItemWithMeta(id: Ident): ConnectionIO[Vector[(RAttachment, FileMeta)]] = {
import bitpeace.sql._
val a = RAttachment.as("a")
val m = RFileMeta.as("m")
@ -301,4 +296,19 @@ object RAttachment {
coll.map(cid => i.cid === cid)
).build.query[RAttachment].streamWithChunkSize(chunkSize)
}
def filterAttachments(
attachments: NonEmptyList[Ident],
coll: Ident
): ConnectionIO[Vector[Ident]] = {
val a = RAttachment.as("a")
val i = RItem.as("i")
Select(
select(a.id),
from(a)
.innerJoin(i, i.id === a.itemId),
i.cid === coll && a.id.in(attachments)
).build.query[Ident].to[Vector]
}
}