Check for an existing item before attempting to add files

This commit is contained in:
Eike Kettner 2020-05-24 10:58:50 +02:00
parent 075b665c68
commit f519a8effa
2 changed files with 58 additions and 17 deletions

View File

@ -1,7 +1,8 @@
package docspell.backend.ops
import bitpeace.MimetypeHint
import cats.data.OptionT
import cats.Functor
import cats.data.{EitherT, OptionT}
import cats.effect._
import cats.implicits._
import docspell.backend.Config
@ -10,7 +11,7 @@ import docspell.common._
import docspell.common.syntax.all._
import docspell.store.Store
import docspell.store.queue.JobQueue
import docspell.store.records.{RCollective, RJob, RSource}
import docspell.store.records._
import org.log4s._
trait OUpload[F[_]] {
@ -55,11 +56,32 @@ object OUpload {
sealed trait UploadResult
object UploadResult {
case object Success extends UploadResult
case object NoFiles extends UploadResult
/** File(s) have been successfully submitted. */
case object Success extends UploadResult
def success: UploadResult = Success
/** There were no files to submit. */
case object NoFiles extends UploadResult
def noFiles: UploadResult = NoFiles
/** A source (`RSource') could not be found for a given source-id. */
case object NoSource extends UploadResult
def noSource: UploadResult = NoSource
/** When adding files to an item, no item was found using the given
* item-id. */
case object NoItem extends UploadResult
def noItem: UploadResult = NoItem
}
private def right[F[_]: Functor, A](a: F[A]): EitherT[F, UploadResult, A] =
EitherT.right(a)
def apply[F[_]: Sync](
store: Store[F],
queue: JobQueue[F],
@ -74,10 +96,11 @@ object OUpload {
notifyJoex: Boolean,
itemId: Option[Ident]
): F[OUpload.UploadResult] =
for {
files <- data.files.traverse(saveFile).map(_.flatten)
pred <- checkFileList(files)
lang <- store.transact(RCollective.findLanguage(account.collective))
(for {
_ <- checkExistingItem(itemId, account.collective)
files <- right(data.files.traverse(saveFile).map(_.flatten))
_ <- checkFileList(files)
lang <- right(store.transact(RCollective.findLanguage(account.collective)))
meta = ProcessItemArgs.ProcessMeta(
account.collective,
itemId,
@ -89,13 +112,15 @@ object OUpload {
args =
if (data.multiple) files.map(f => ProcessItemArgs(meta, List(f)))
else Vector(ProcessItemArgs(meta, files.toList))
job <- pred.traverse(_ => makeJobs(args, account, data.priority, data.tracker))
_ <- logger.fdebug(s"Storing jobs: $job")
res <- job.traverse(submitJobs(notifyJoex))
_ <- store.transact(
RSource.incrementCounter(data.meta.sourceAbbrev, account.collective)
jobs <- right(makeJobs(args, account, data.priority, data.tracker))
_ <- right(logger.fdebug(s"Storing jobs: $jobs"))
res <- right(submitJobs(notifyJoex)(jobs))
_ <- right(
store.transact(
RSource.incrementCounter(data.meta.sourceAbbrev, account.collective)
)
)
} yield res.fold(identity, identity)
} yield res).fold(identity, identity)
def submit(
data: OUpload.UploadData[F],
@ -111,7 +136,7 @@ object OUpload {
)
accId = AccountId(src.cid, src.sid)
result <- OptionT.liftF(submit(updata, accId, notifyJoex, itemId))
} yield result).getOrElse(UploadResult.NoSource)
} yield result).getOrElse(UploadResult.noSource)
private def submitJobs(
notifyJoex: Boolean
@ -122,6 +147,7 @@ object OUpload {
_ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F]
} yield UploadResult.Success
/** Saves the file into the database. */
private def saveFile(file: File[F]): F[Option[ProcessItemArgs.File]] =
logger.finfo(s"Receiving file $file") *>
store.bitpeace
@ -140,10 +166,24 @@ object OUpload {
)
)
private def checkExistingItem(
itemId: Option[Ident],
coll: Ident
): EitherT[F, UploadResult, Unit] =
itemId match {
case None =>
right(().pure[F])
case Some(id) =>
OptionT(store.transact(RItem.findByIdAndCollective(id, coll)))
.toRight(UploadResult.noItem)
.map(_ => ())
}
private def checkFileList(
files: Seq[ProcessItemArgs.File]
): F[Either[UploadResult, Unit]] =
Sync[F].pure(if (files.isEmpty) Left(UploadResult.NoFiles) else Right(()))
): EitherT[F, UploadResult, Unit] =
if (files.isEmpty) EitherT.left(UploadResult.noFiles.pure[F])
else right(().pure[F])
private def makeJobs(
args: Vector[ProcessItemArgs],

View File

@ -470,6 +470,7 @@ trait Conversions {
case UploadResult.Success => BasicResult(true, "Files submitted.")
case UploadResult.NoFiles => BasicResult(false, "There were no files to submit.")
case UploadResult.NoSource => BasicResult(false, "The source id is not valid.")
case UploadResult.NoItem => BasicResult(false, "The item could not be found.")
}
def basicResult(cr: PassChangeResult): BasicResult =