Add a file-repository for better organizing files

Docspell now must use a new api for accessing files.

Issue: #1379
This commit is contained in:
eikek
2022-02-13 12:08:01 +01:00
parent 3dcb113cef
commit 553b1fa249
40 changed files with 451 additions and 232 deletions

View File

@ -0,0 +1,46 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package docspell.common
import cats.data.NonEmptyList
import docspell.common
import io.circe.{Decoder, Encoder}
/** This is used to have a rough idea for what a file is used in the system. It is part of
* the file-key to identify a file, backends could ignore it, since the file-id (the last
* part of the file-key) should be globally unique anyways.
*/
sealed trait FileCategory { self: Product =>
final def id: Ident =
Ident.unsafe(self.productPrefix.toLowerCase)
def toFileKey(collective: Ident, fileId: Ident): FileKey =
common.FileKey(collective, this, fileId)
}
object FileCategory {
// Impl note: Changing constants here requires a database migration!
case object AttachmentSource extends FileCategory
case object AttachmentConvert extends FileCategory
case object PreviewImage extends FileCategory
case object Classifier extends FileCategory
val all: NonEmptyList[FileCategory] =
NonEmptyList.of(AttachmentSource, AttachmentConvert, PreviewImage, Classifier)
def fromString(str: String): Either[String, FileCategory] =
all.find(_.id.id == str).toRight(s"Unknown category: $str")
implicit val jsonDecoder: Decoder[FileCategory] =
Decoder[String].emap(fromString)
implicit val jsonEncoder: Encoder[FileCategory] =
Encoder[String].contramap(_.id.id)
}

View File

@ -0,0 +1,21 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package docspell.common
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
case class FileKey(collective: Ident, category: FileCategory, id: Ident)
object FileKey {
implicit val jsonDecoder: Decoder[FileKey] =
deriveDecoder[FileKey]
implicit val jsonEncoder: Encoder[FileKey] =
deriveEncoder[FileKey]
}

View File

@ -25,13 +25,15 @@ case class Ident(id: String) {
!isEmpty
def /(next: Ident): Ident =
new Ident(id + "." + next.id)
new Ident(id + Ident.concatChar + next.id)
}
object Ident {
private val concatChar = '.'
implicit val identEq: Eq[Ident] =
Eq.by(_.id)
// Note, the slash *must not* be part of valid characters
val chars: Set[Char] = (('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') ++ "-_.@").toSet
def randomUUID[F[_]: Sync]: F[Ident] =
@ -75,5 +77,4 @@ object Ident {
implicit val order: Order[Ident] =
Order.by(_.id)
}

View File

@ -60,7 +60,7 @@ object ProcessItemArgs {
implicit val jsonDecoder: Decoder[ProcessMeta] = deriveDecoder[ProcessMeta]
}
case class File(name: Option[String], fileMetaId: Ident)
case class File(name: Option[String], fileMetaId: FileKey)
object File {
implicit val jsonEncoder: Encoder[File] = deriveEncoder[File]
implicit val jsonDecoder: Decoder[File] = deriveDecoder[File]