Adopt restserver to new collective-id

This commit is contained in:
eikek
2022-08-04 12:44:09 +02:00
parent 53d92c4a26
commit eabcffe71a
48 changed files with 539 additions and 293 deletions

View File

@ -28,7 +28,6 @@ trait OCollective[F[_]] {
def updateSettings( def updateSettings(
collective: CollectiveId, collective: CollectiveId,
collectiveName: Ident,
settings: OCollective.Settings settings: OCollective.Settings
): F[AddResult] ): F[AddResult]
@ -147,7 +146,6 @@ object OCollective {
def updateSettings( def updateSettings(
collectiveId: CollectiveId, collectiveId: CollectiveId,
collectiveName: Ident,
sett: Settings sett: Settings
): F[AddResult] = ): F[AddResult] =
store store

View File

@ -40,10 +40,10 @@ trait ODownloadAll[F[_]] {
def submit(accountId: AccountInfo, req: DownloadRequest): F[DownloadSummary] def submit(accountId: AccountInfo, req: DownloadRequest): F[DownloadSummary]
/** Given the id from the summary, cancels a running job. */ /** Given the id from the summary, cancels a running job. */
def cancelDownload(accountId: AccountId, id: Ident): F[OJob.JobCancelResult] def cancelDownload(cid: CollectiveId, id: Ident): F[OJob.JobCancelResult]
/** Returns the file if it is present, given a summary id. */ /** Returns the file if it is present, given a summary id. */
def getFile(collective: Ident, id: Ident): F[Option[DownloadAllFile[F]]] def getFile(collective: CollectiveId, id: Ident): F[Option[DownloadAllFile[F]]]
/** Deletes a download archive given it's id. */ /** Deletes a download archive given it's id. */
def deleteFile(id: Ident): F[Unit] def deleteFile(id: Ident): F[Unit]
@ -122,7 +122,7 @@ object ODownloadAll {
else DownloadState.NotPresent else DownloadState.NotPresent
} yield state } yield state
def getFile(collective: Ident, id: Ident) = def getFile(collective: CollectiveId, id: Ident) =
OptionT(store.transact(RDownloadQuery.findById(id))) OptionT(store.transact(RDownloadQuery.findById(id)))
.map(_._2) .map(_._2)
.map(md => .map(md =>
@ -156,10 +156,10 @@ object ODownloadAll {
_ <- store.fileRepo.delete(fkey) _ <- store.fileRepo.delete(fkey)
} yield () } yield ()
def cancelDownload(accountId: AccountId, id: Ident) = def cancelDownload(cid: CollectiveId, id: Ident) =
OptionT(store.transact(RDownloadQuery.findById(id))) OptionT(store.transact(RDownloadQuery.findById(id)))
.flatMap(t => OptionT(store.transact(RJob.findNonFinalByTracker(t._1.id)))) .flatMap(t => OptionT(store.transact(RJob.findNonFinalByTracker(t._1.id))))
.semiflatMap(job => jobs.cancelJob(job.id, accountId.collective)) .semiflatMap(job => jobs.cancelJob(job.id, UserTaskScope.collective(cid)))
.getOrElse(JobCancelResult.jobNotFound) .getOrElse(JobCancelResult.jobNotFound)
} }

View File

@ -30,10 +30,10 @@ trait OFolder[F[_]] {
userId: Ident userId: Ident
): F[Option[OFolder.FolderDetail]] ): F[Option[OFolder.FolderDetail]]
/** Adds a new folder. If `login` is non-empty, the `folder.user` property is ignored /** Adds a new folder. If `login` is non-empty, the `folder.owner` property is ignored
* and the user-id is determined by the given login name. * and its value is determined by the given login name.
*/ */
def add(folder: RFolder, userId: Option[Ident]): F[AddResult] def add(folder: RFolder, login: Option[Ident]): F[AddResult]
def changeName( def changeName(
folder: Ident, folder: Ident,
@ -123,11 +123,11 @@ object OFolder {
): F[Option[FolderDetail]] = ): F[Option[FolderDetail]] =
store.transact(QFolder.findById(id, collectiveId, userId)) store.transact(QFolder.findById(id, collectiveId, userId))
def add(folder: RFolder, userId: Option[Ident]): F[AddResult] = { def add(folder: RFolder, login: Option[Ident]): F[AddResult] = {
val insert = userId match { val insert = login match {
case Some(uid) => case Some(userLogin) =>
for { for {
user <- RUser.findById(uid, folder.collectiveId.some) user <- RUser.findByLogin(userLogin, folder.collectiveId.some)
s = user.map(u => folder.copy(owner = u.uid)).getOrElse(folder) s = user.map(u => folder.copy(owner = u.uid)).getOrElse(folder)
n <- RFolder.insert(s) n <- RFolder.insert(s)
} yield n } yield n

View File

@ -9,11 +9,11 @@ package docspell.backend.ops
import cats.data.OptionT import cats.data.OptionT
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.ops.OJob.{CollectiveQueueState, JobCancelResult} import docspell.backend.ops.OJob.{CollectiveQueueState, JobCancelResult}
import docspell.common._ import docspell.common._
import docspell.pubsub.api.PubSubT import docspell.pubsub.api.PubSubT
import docspell.scheduler.msg.JobDone import docspell.scheduler.msg.JobDone
import docspell.scheduler.usertask.UserTaskScope
import docspell.store.Store import docspell.store.Store
import docspell.store.UpdateResult import docspell.store.UpdateResult
import docspell.store.queries.QJobQueue import docspell.store.queries.QJobQueue
@ -21,13 +21,13 @@ import docspell.store.records.{RJob, RJobLog}
trait OJob[F[_]] { trait OJob[F[_]] {
def queueState(collective: Ident, maxResults: Int): F[CollectiveQueueState] def queueState(collective: UserTaskScope, maxResults: Int): F[CollectiveQueueState]
def cancelJob(id: Ident, collective: Ident): F[JobCancelResult] def cancelJob(id: Ident, collective: UserTaskScope): F[JobCancelResult]
def setPriority(id: Ident, collective: Ident, prio: Priority): F[UpdateResult] def setPriority(id: Ident, collective: UserTaskScope, prio: Priority): F[UpdateResult]
def getUnfinishedJobCount(collective: Ident): F[Int] def getUnfinishedJobCount(collective: UserTaskScope): F[Int]
} }
object OJob { object OJob {
@ -61,20 +61,34 @@ object OJob {
Resource.pure[F, OJob[F]](new OJob[F] { Resource.pure[F, OJob[F]](new OJob[F] {
private[this] val logger = docspell.logging.getLogger[F] private[this] val logger = docspell.logging.getLogger[F]
def queueState(collective: Ident, maxResults: Int): F[CollectiveQueueState] = private def scopeToGroup(s: UserTaskScope) =
s.collectiveId
.map(_.valueAsIdent)
.getOrElse(DocspellSystem.taskGroup)
def queueState(
collective: UserTaskScope,
maxResults: Int
): F[CollectiveQueueState] =
store store
.transact( .transact(
QJobQueue.queueStateSnapshot(collective, maxResults.toLong) QJobQueue.queueStateSnapshot(scopeToGroup(collective), maxResults.toLong)
) )
.map(t => JobDetail(t._1, t._2)) .map(t => JobDetail(t._1, t._2))
.compile .compile
.toVector .toVector
.map(CollectiveQueueState) .map(CollectiveQueueState)
def setPriority(id: Ident, collective: Ident, prio: Priority): F[UpdateResult] = def setPriority(
UpdateResult.fromUpdate(store.transact(RJob.setPriority(id, collective, prio))) id: Ident,
collective: UserTaskScope,
prio: Priority
): F[UpdateResult] =
UpdateResult.fromUpdate(
store.transact(RJob.setPriority(id, scopeToGroup(collective), prio))
)
def cancelJob(id: Ident, collective: Ident): F[JobCancelResult] = { def cancelJob(id: Ident, collective: UserTaskScope): F[JobCancelResult] = {
def remove(job: RJob): F[JobCancelResult] = def remove(job: RJob): F[JobCancelResult] =
for { for {
n <- store.transact(RJob.delete(job.id)) n <- store.transact(RJob.delete(job.id))
@ -99,7 +113,9 @@ object OJob {
} }
(for { (for {
job <- OptionT(store.transact(RJob.findByIdAndGroup(id, collective))) job <- OptionT(
store.transact(RJob.findByIdAndGroup(id, scopeToGroup(collective)))
)
result <- OptionT.liftF( result <- OptionT.liftF(
if (job.isInProgress) tryCancel(job) if (job.isInProgress) tryCancel(job)
else remove(job) else remove(job)
@ -108,7 +124,7 @@ object OJob {
.getOrElse(JobCancelResult.jobNotFound) .getOrElse(JobCancelResult.jobNotFound)
} }
def getUnfinishedJobCount(collective: Ident): F[Int] = def getUnfinishedJobCount(collective: UserTaskScope): F[Int] =
store.transact(RJob.getUnfinishedCount(collective)) store.transact(RJob.getUnfinishedCount(scopeToGroup(collective)))
}) })
} }

View File

@ -20,7 +20,7 @@ import io.circe.generic.semiauto._
*/ */
case class ScanMailboxArgs( case class ScanMailboxArgs(
// the docspell user account // the docspell user account
account: AccountId, account: AccountInfo,
// the configured imap connection // the configured imap connection
imapConnection: Ident, imapConnection: Ident,
// scan folders recursively // scan folders recursively

View File

@ -21,7 +21,7 @@ import io.circe.{Decoder, Encoder}
* the json data of the corresponding task. * the json data of the corresponding task.
*/ */
final case class PeriodicDueItemsArgs( final case class PeriodicDueItemsArgs(
account: AccountId, account: AccountInfo,
channels: NonEmptyList[ChannelRef], channels: NonEmptyList[ChannelRef],
remindDays: Int, remindDays: Int,
daysBack: Option[Int], daysBack: Option[Int],

View File

@ -14,7 +14,7 @@ import io.circe.generic.semiauto
import io.circe.{Decoder, Encoder} import io.circe.{Decoder, Encoder}
final case class PeriodicQueryArgs( final case class PeriodicQueryArgs(
account: AccountId, account: AccountInfo,
channels: NonEmptyList[ChannelRef], channels: NonEmptyList[ChannelRef],
query: Option[ItemQueryString], query: Option[ItemQueryString],
bookmark: Option[String], bookmark: Option[String],

View File

@ -7,14 +7,12 @@
package docspell.restserver.auth package docspell.restserver.auth
import docspell.backend.auth._ import docspell.backend.auth._
import docspell.common.AccountId import docspell.common.{AccountInfo, LenientUri}
import docspell.common.LenientUri
import org.http4s._ import org.http4s._
import org.typelevel.ci.CIString import org.typelevel.ci.CIString
case class CookieData(auth: AuthToken) { case class CookieData(auth: AuthToken) {
def accountId: AccountId = auth.account def accountInfo: AccountInfo = auth.account
def asString: String = auth.asString def asString: String = auth.asString
def asCookie(baseUrl: LenientUri): ResponseCookie = { def asCookie(baseUrl: LenientUri): ResponseCookie = {

View File

@ -371,7 +371,10 @@ trait Conversions {
) )
} }
def newOrg[F[_]: Sync](v: Organization, cid: Ident): F[OOrganization.OrgAndContacts] = { def newOrg[F[_]: Sync](
v: Organization,
cid: CollectiveId
): F[OOrganization.OrgAndContacts] = {
def contacts(oid: Ident) = def contacts(oid: Ident) =
v.contacts.traverse(c => newContact(c, oid.some, None)) v.contacts.traverse(c => newContact(c, oid.some, None))
for { for {
@ -397,7 +400,7 @@ trait Conversions {
def changeOrg[F[_]: Sync]( def changeOrg[F[_]: Sync](
v: Organization, v: Organization,
cid: Ident cid: CollectiveId
): F[OOrganization.OrgAndContacts] = { ): F[OOrganization.OrgAndContacts] = {
def contacts(oid: Ident) = def contacts(oid: Ident) =
v.contacts.traverse(c => newContact(c, oid.some, None)) v.contacts.traverse(c => newContact(c, oid.some, None))
@ -435,7 +438,10 @@ trait Conversions {
) )
} }
def newPerson[F[_]: Sync](v: Person, cid: Ident): F[OOrganization.PersonAndContacts] = { def newPerson[F[_]: Sync](
v: Person,
cid: CollectiveId
): F[OOrganization.PersonAndContacts] = {
def contacts(pid: Ident) = def contacts(pid: Ident) =
v.contacts.traverse(c => newContact(c, None, pid.some)) v.contacts.traverse(c => newContact(c, None, pid.some))
for { for {
@ -461,7 +467,7 @@ trait Conversions {
def changePerson[F[_]: Sync]( def changePerson[F[_]: Sync](
v: Person, v: Person,
cid: Ident cid: CollectiveId
): F[OOrganization.PersonAndContacts] = { ): F[OOrganization.PersonAndContacts] = {
def contacts(pid: Ident) = def contacts(pid: Ident) =
v.contacts.traverse(c => newContact(c, None, pid.some)) v.contacts.traverse(c => newContact(c, None, pid.some))
@ -512,7 +518,7 @@ trait Conversions {
ru.created ru.created
) )
def newUser[F[_]: Sync](u: User, cid: Ident): F[RUser] = def newUser[F[_]: Sync](u: User, cid: CollectiveId): F[RUser] =
Conversions.timeId.map { case (id, now) => Conversions.timeId.map { case (id, now) =>
RUser( RUser(
id, id,
@ -528,7 +534,7 @@ trait Conversions {
) )
} }
def changeUser(u: User, cid: Ident): RUser = def changeUser(u: User, cid: CollectiveId): RUser =
RUser( RUser(
u.id, u.id,
u.login, u.login,
@ -547,12 +553,12 @@ trait Conversions {
def mkTag(rt: RTag): Tag = def mkTag(rt: RTag): Tag =
Tag(rt.tagId, rt.name, rt.category, rt.created) Tag(rt.tagId, rt.name, rt.category, rt.created)
def newTag[F[_]: Sync](t: Tag, cid: Ident): F[RTag] = def newTag[F[_]: Sync](t: Tag, cid: CollectiveId): F[RTag] =
Conversions.timeId.map { case (id, now) => Conversions.timeId.map { case (id, now) =>
RTag(id, cid, t.name.trim, t.category.map(_.trim), now) RTag(id, cid, t.name.trim, t.category.map(_.trim), now)
} }
def changeTag(t: Tag, cid: Ident): RTag = def changeTag(t: Tag, cid: CollectiveId): RTag =
RTag(t.id, cid, t.name.trim, t.category.map(_.trim), t.created) RTag(t.id, cid, t.name.trim, t.category.map(_.trim), t.created)
// sources // sources
@ -575,7 +581,7 @@ trait Conversions {
TagList(s.tags.length, s.tags.map(mkTag).toList) TagList(s.tags.length, s.tags.map(mkTag).toList)
) )
def newSource[F[_]: Sync](s: Source, cid: Ident): F[RSource] = def newSource[F[_]: Sync](s: Source, cid: CollectiveId): F[RSource] =
Conversions.timeId.map { case (id, now) => Conversions.timeId.map { case (id, now) =>
RSource( RSource(
id, id,
@ -593,10 +599,10 @@ trait Conversions {
) )
} }
def changeSource[F[_]](s: Source, coll: Ident): RSource = def changeSource(s: Source, cid: CollectiveId): RSource =
RSource( RSource(
s.id, s.id,
coll, cid,
s.abbrev.trim, s.abbrev.trim,
s.description, s.description,
s.counter, s.counter,
@ -613,12 +619,12 @@ trait Conversions {
def mkEquipment(re: REquipment): Equipment = def mkEquipment(re: REquipment): Equipment =
Equipment(re.eid, re.name, re.created, re.notes, re.use) Equipment(re.eid, re.name, re.created, re.notes, re.use)
def newEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = def newEquipment[F[_]: Sync](e: Equipment, cid: CollectiveId): F[REquipment] =
Conversions.timeId.map { case (id, now) => Conversions.timeId.map { case (id, now) =>
REquipment(id, cid, e.name.trim, now, now, e.notes, e.use) REquipment(id, cid, e.name.trim, now, now, e.notes, e.use)
} }
def changeEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = def changeEquipment[F[_]: Sync](e: Equipment, cid: CollectiveId): F[REquipment] =
Timestamp Timestamp
.current[F] .current[F]
.map(now => REquipment(e.id, cid, e.name.trim, e.created, now, e.notes, e.use)) .map(now => REquipment(e.id, cid, e.name.trim, e.created, now, e.notes, e.use))
@ -681,6 +687,8 @@ trait Conversions {
case UploadResult.NoFiles => BasicResult(false, "There were no files to submit.") case UploadResult.NoFiles => BasicResult(false, "There were no files to submit.")
case UploadResult.NoSource => BasicResult(false, "The source id is not valid.") case UploadResult.NoSource => BasicResult(false, "The source id is not valid.")
case UploadResult.NoItem => BasicResult(false, "The item could not be found.") case UploadResult.NoItem => BasicResult(false, "The item could not be found.")
case UploadResult.NoCollective =>
BasicResult(false, "The collective could not be found.")
} }
def basicResult(cr: PassChangeResult): BasicResult = def basicResult(cr: PassChangeResult): BasicResult =

View File

@ -39,7 +39,7 @@ object AddonArchiveRoutes extends AddonValidationSupport {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
for { for {
all <- backend.addons.getAllAddons(token.account.collective) all <- backend.addons.getAllAddons(token.account.collectiveId)
resp <- Ok( resp <- Ok(
AddonList( AddonList(
all.map(r => all.map(r =>
@ -62,7 +62,7 @@ object AddonArchiveRoutes extends AddonValidationSupport {
for { for {
input <- req.as[AddonRegister] input <- req.as[AddonRegister]
install = backend.addons.registerAddon( install = backend.addons.registerAddon(
token.account.collective, token.account.collectiveId,
input.url, input.url,
None None
) )
@ -82,7 +82,7 @@ object AddonArchiveRoutes extends AddonValidationSupport {
s"Addon updated: ${m.nameAndVersion}" s"Addon updated: ${m.nameAndVersion}"
) )
) )
val update = backend.addons.refreshAddon(token.account.collective, id) val update = backend.addons.refreshAddon(token.account.collectiveId, id)
for { for {
resp <- resp <-
if (sync) if (sync)
@ -97,7 +97,7 @@ object AddonArchiveRoutes extends AddonValidationSupport {
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
flag <- backend.addons.deleteAddon(token.account.collective, id) flag <- backend.addons.deleteAddon(token.account.collectiveId, id)
resp <- resp <-
if (flag) Ok(BasicResult(true, "Addon deleted")) if (flag) Ok(BasicResult(true, "Addon deleted"))
else NotFound(BasicResult(false, "Addon not found")) else NotFound(BasicResult(false, "Addon not found"))

View File

@ -29,7 +29,7 @@ object AddonRunConfigRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
for { for {
all <- backend.addons.getAllAddonRunConfigs(token.account.collective) all <- backend.addons.getAllAddonRunConfigs(token.account.collectiveId)
resp <- Ok(AddonRunConfigList(all.map(convertInfoTask))) resp <- Ok(AddonRunConfigList(all.map(convertInfoTask)))
} yield resp } yield resp
@ -39,7 +39,7 @@ object AddonRunConfigRoutes {
data = convertInsertTask(Ident.unsafe(""), input) data = convertInsertTask(Ident.unsafe(""), input)
res <- data.flatTraverse(in => res <- data.flatTraverse(in =>
backend.addons backend.addons
.upsertAddonRunConfig(token.account.collective, in) .upsertAddonRunConfig(token.account.collectiveId, in)
.map(_.leftMap(_.message)) .map(_.leftMap(_.message))
) )
resp <- res.fold( resp <- res.fold(
@ -54,7 +54,7 @@ object AddonRunConfigRoutes {
data = convertInsertTask(id, input) data = convertInsertTask(id, input)
res <- data.flatTraverse(in => res <- data.flatTraverse(in =>
backend.addons backend.addons
.upsertAddonRunConfig(token.account.collective, in) .upsertAddonRunConfig(token.account.collectiveId, in)
.map(_.leftMap(_.message)) .map(_.leftMap(_.message))
) )
resp <- res.fold( resp <- res.fold(
@ -65,7 +65,7 @@ object AddonRunConfigRoutes {
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
flag <- backend.addons.deleteAddonRunConfig(token.account.collective, id) flag <- backend.addons.deleteAddonRunConfig(token.account.collectiveId, id)
resp <- resp <-
if (flag) Ok(BasicResult(true, "Addon task deleted")) if (flag) Ok(BasicResult(true, "Addon task deleted"))
else NotFound(BasicResult(false, "Addon task not found")) else NotFound(BasicResult(false, "Addon task not found"))

View File

@ -9,12 +9,11 @@ package docspell.restserver.routes
import cats.data.NonEmptyList import cats.data.NonEmptyList
import cats.effect._ import cats.effect._
import cats.syntax.all._ import cats.syntax.all._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.restapi.model._ import docspell.restapi.model._
import docspell.restserver.http4s.ThrowableResponseMapper import docspell.restserver.http4s.ThrowableResponseMapper
import docspell.scheduler.usertask.UserTaskScope
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityCodec._ import org.http4s.circe.CirceEntityCodec._
import org.http4s.dsl.Http4sDsl import org.http4s.dsl.Http4sDsl
@ -29,9 +28,10 @@ object AddonRunRoutes {
for { for {
input <- req.as[AddonRunExistingItem] input <- req.as[AddonRunExistingItem]
_ <- backend.addons.runAddonForItem( _ <- backend.addons.runAddonForItem(
token.account, token.account.collectiveId,
NonEmptyList(input.itemId, input.additionalItems), NonEmptyList(input.itemId, input.additionalItems),
input.addonRunConfigIds.toSet input.addonRunConfigIds.toSet,
UserTaskScope(token.account)
) )
resp <- Ok(BasicResult(true, "Job for running addons submitted.")) resp <- Ok(BasicResult(true, "Job for running addons submitted."))
} yield resp } yield resp

View File

@ -33,7 +33,7 @@ object AttachmentMultiRoutes extends NonEmptyListSupport {
for { for {
json <- req.as[IdList] json <- req.as[IdList]
attachments <- requireNonEmpty(json.ids) attachments <- requireNonEmpty(json.ids)
n <- backend.item.deleteAttachmentMultiple(attachments, user.account.collective) n <- backend.item.deleteAttachmentMultiple(attachments, user.account.collectiveId)
res = BasicResult( res = BasicResult(
n > 0, n > 0,
if (n > 0) "Attachment(s) deleted" else "Attachment deletion failed." if (n > 0) "Attachment(s) deleted" else "Attachment deletion failed."

View File

@ -8,7 +8,6 @@ package docspell.restserver.routes
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.backend.ops._ import docspell.backend.ops._
@ -18,7 +17,7 @@ import docspell.restapi.model._
import docspell.restserver.conv.Conversions import docspell.restserver.conv.Conversions
import docspell.restserver.http4s.BinaryUtil import docspell.restserver.http4s.BinaryUtil
import docspell.restserver.webapp.Webjars import docspell.restserver.webapp.Webjars
import docspell.scheduler.usertask.UserTaskScope
import org.http4s._ import org.http4s._
import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
@ -45,19 +44,22 @@ object AttachmentRoutes {
HttpRoutes.of { HttpRoutes.of {
case HEAD -> Root / Ident(id) => case HEAD -> Root / Ident(id) =>
for { for {
fileData <- backend.itemSearch.findAttachment(id, user.account.collective) fileData <- backend.itemSearch.findAttachment(id, user.account.collectiveId)
resp <- BinaryUtil.respondHead(dsl)(fileData) resp <- BinaryUtil.respondHead(dsl)(fileData)
} yield resp } yield resp
case req @ GET -> Root / Ident(id) => case req @ GET -> Root / Ident(id) =>
for { for {
fileData <- backend.itemSearch.findAttachment(id, user.account.collective) fileData <- backend.itemSearch.findAttachment(id, user.account.collectiveId)
resp <- BinaryUtil.respond[F](dsl, req)(fileData) resp <- BinaryUtil.respond[F](dsl, req)(fileData)
} yield resp } yield resp
case HEAD -> Root / Ident(id) / "original" => case HEAD -> Root / Ident(id) / "original" =>
for { for {
fileData <- backend.itemSearch.findAttachmentSource(id, user.account.collective) fileData <- backend.itemSearch.findAttachmentSource(
id,
user.account.collectiveId
)
resp <- resp <-
fileData fileData
.map(data => withResponseHeaders(Ok())(data)) .map(data => withResponseHeaders(Ok())(data))
@ -66,7 +68,10 @@ object AttachmentRoutes {
case req @ GET -> Root / Ident(id) / "original" => case req @ GET -> Root / Ident(id) / "original" =>
for { for {
fileData <- backend.itemSearch.findAttachmentSource(id, user.account.collective) fileData <- backend.itemSearch.findAttachmentSource(
id,
user.account.collectiveId
)
inm = req.headers.get[`If-None-Match`].flatMap(_.tags) inm = req.headers.get[`If-None-Match`].flatMap(_.tags)
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm) matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
resp <- resp <-
@ -81,7 +86,7 @@ object AttachmentRoutes {
case HEAD -> Root / Ident(id) / "archive" => case HEAD -> Root / Ident(id) / "archive" =>
for { for {
fileData <- fileData <-
backend.itemSearch.findAttachmentArchive(id, user.account.collective) backend.itemSearch.findAttachmentArchive(id, user.account.collectiveId)
resp <- resp <-
fileData fileData
.map(data => withResponseHeaders(Ok())(data)) .map(data => withResponseHeaders(Ok())(data))
@ -91,7 +96,7 @@ object AttachmentRoutes {
case req @ GET -> Root / Ident(id) / "archive" => case req @ GET -> Root / Ident(id) / "archive" =>
for { for {
fileData <- fileData <-
backend.itemSearch.findAttachmentArchive(id, user.account.collective) backend.itemSearch.findAttachmentArchive(id, user.account.collectiveId)
inm = req.headers.get[`If-None-Match`].flatMap(_.tags) inm = req.headers.get[`If-None-Match`].flatMap(_.tags)
matches = BinaryUtil.matchETag(fileData.map(_.meta), inm) matches = BinaryUtil.matchETag(fileData.map(_.meta), inm)
resp <- resp <-
@ -106,14 +111,14 @@ object AttachmentRoutes {
case req @ GET -> Root / Ident(id) / "preview" => case req @ GET -> Root / Ident(id) / "preview" =>
for { for {
fileData <- fileData <-
backend.itemSearch.findAttachmentPreview(id, user.account.collective) backend.itemSearch.findAttachmentPreview(id, user.account.collectiveId)
resp <- BinaryUtil.respondPreview(dsl, req)(fileData) resp <- BinaryUtil.respondPreview(dsl, req)(fileData)
} yield resp } yield resp
case HEAD -> Root / Ident(id) / "preview" => case HEAD -> Root / Ident(id) / "preview" =>
for { for {
fileData <- fileData <-
backend.itemSearch.findAttachmentPreview(id, user.account.collective) backend.itemSearch.findAttachmentPreview(id, user.account.collectiveId)
resp <- BinaryUtil.respondPreviewHead(dsl)(fileData) resp <- BinaryUtil.respondPreviewHead(dsl)(fileData)
} yield resp } yield resp
@ -121,7 +126,7 @@ object AttachmentRoutes {
for { for {
res <- backend.item.generatePreview( res <- backend.item.generatePreview(
MakePreviewArgs.replace(id), MakePreviewArgs.replace(id),
user.account UserTaskScope(user.account)
) )
resp <- Ok( resp <- Ok(
Conversions.basicResult(res, "Generating preview image task submitted.") Conversions.basicResult(res, "Generating preview image task submitted.")
@ -138,7 +143,7 @@ object AttachmentRoutes {
case GET -> Root / Ident(id) / "meta" => case GET -> Root / Ident(id) / "meta" =>
for { for {
rm <- backend.itemSearch.findAttachmentMeta(id, user.account.collective) rm <- backend.itemSearch.findAttachmentMeta(id, user.account.collectiveId)
md = rm.map(Conversions.mkAttachmentMeta) md = rm.map(Conversions.mkAttachmentMeta)
resp <- md.map(Ok(_)).getOrElse(NotFound(BasicResult(false, "Not found."))) resp <- md.map(Ok(_)).getOrElse(NotFound(BasicResult(false, "Not found.")))
} yield resp } yield resp
@ -146,13 +151,13 @@ object AttachmentRoutes {
case req @ POST -> Root / Ident(id) / "name" => case req @ POST -> Root / Ident(id) / "name" =>
for { for {
nn <- req.as[OptionalText] nn <- req.as[OptionalText]
res <- backend.item.setAttachmentName(id, nn.text, user.account.collective) res <- backend.item.setAttachmentName(id, nn.text, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Name updated.")) resp <- Ok(Conversions.basicResult(res, "Name updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
n <- backend.item.deleteAttachment(id, user.account.collective) n <- backend.item.deleteAttachment(id, user.account.collectiveId)
res = res =
if (n == 0) BasicResult(false, "Attachment not found") if (n == 0) BasicResult(false, "Attachment not found")
else BasicResult(true, "Attachment deleted.") else BasicResult(true, "Attachment deleted.")
@ -177,10 +182,9 @@ object AttachmentRoutes {
case POST -> Root / "convertallpdfs" => case POST -> Root / "convertallpdfs" =>
for { for {
res <- res <-
backend.item.convertAllPdf(None, None) backend.item.convertAllPdf(None, UserTaskScope.system)
resp <- Ok(Conversions.basicResult(res, "Convert all PDFs task submitted")) resp <- Ok(Conversions.basicResult(res, "Convert all PDFs task submitted"))
} yield resp } yield resp
} }
} }
} }

View File

@ -29,7 +29,7 @@ object CheckFileRoutes {
HttpRoutes.of { case GET -> Root / checksum => HttpRoutes.of { case GET -> Root / checksum =>
for { for {
items <- items <-
backend.itemSearch.findByFileCollective(checksum, user.account.collective) backend.itemSearch.findByFileCollective(checksum, user.account.collectiveId)
resp <- Ok(convert(items)) resp <- Ok(convert(items))
} yield resp } yield resp

View File

@ -36,7 +36,7 @@ object ClientSettingsRoutes {
_ <- OptionT.liftF(logger.debug(s"Get client settings for share ${token.id}")) _ <- OptionT.liftF(logger.debug(s"Get client settings for share ${token.id}"))
share <- backend.share.findActiveById(token.id) share <- backend.share.findActiveById(token.id)
sett <- OptionT( sett <- OptionT(
backend.clientSettings.loadCollective(clientId, share.user.accountId) backend.clientSettings.loadCollective(clientId, share.account.collectiveId)
) )
res <- OptionT.liftF(Ok(sett.settingsData)) res <- OptionT.liftF(Ok(sett.settingsData))
} yield res) } yield res)
@ -51,7 +51,11 @@ object ClientSettingsRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root / Ident(clientId) => case GET -> Root / Ident(clientId) =>
for { for {
mergedData <- backend.clientSettings.loadMerged(clientId, user.account) mergedData <- backend.clientSettings.loadMerged(
clientId,
user.account.collectiveId,
user.account.userId
)
res <- mergedData match { res <- mergedData match {
case Some(j) => Ok(j) case Some(j) => Ok(j)
case None => Ok(Map.empty[String, String]) case None => Ok(Map.empty[String, String])
@ -61,13 +65,13 @@ object ClientSettingsRoutes {
case req @ PUT -> Root / "user" / Ident(clientId) => case req @ PUT -> Root / "user" / Ident(clientId) =>
for { for {
data <- req.as[Json] data <- req.as[Json]
_ <- backend.clientSettings.saveUser(clientId, user.account, data) _ <- backend.clientSettings.saveUser(clientId, user.account.userId, data)
res <- Ok(BasicResult(true, "Settings stored")) res <- Ok(BasicResult(true, "Settings stored"))
} yield res } yield res
case GET -> Root / "user" / Ident(clientId) => case GET -> Root / "user" / Ident(clientId) =>
for { for {
data <- backend.clientSettings.loadUser(clientId, user.account) data <- backend.clientSettings.loadUser(clientId, user.account.userId)
res <- data match { res <- data match {
case Some(d) => Ok(d.settingsData) case Some(d) => Ok(d.settingsData)
case None => Ok(Map.empty[String, String]) case None => Ok(Map.empty[String, String])
@ -76,7 +80,7 @@ object ClientSettingsRoutes {
case DELETE -> Root / "user" / Ident(clientId) => case DELETE -> Root / "user" / Ident(clientId) =>
for { for {
flag <- backend.clientSettings.deleteUser(clientId, user.account) flag <- backend.clientSettings.deleteUser(clientId, user.account.userId)
res <- Ok( res <- Ok(
BasicResult( BasicResult(
flag, flag,
@ -88,13 +92,20 @@ object ClientSettingsRoutes {
case req @ PUT -> Root / "collective" / Ident(clientId) => case req @ PUT -> Root / "collective" / Ident(clientId) =>
for { for {
data <- req.as[Json] data <- req.as[Json]
_ <- backend.clientSettings.saveCollective(clientId, user.account, data) _ <- backend.clientSettings.saveCollective(
clientId,
user.account.collectiveId,
data
)
res <- Ok(BasicResult(true, "Settings stored")) res <- Ok(BasicResult(true, "Settings stored"))
} yield res } yield res
case GET -> Root / "collective" / Ident(clientId) => case GET -> Root / "collective" / Ident(clientId) =>
for { for {
data <- backend.clientSettings.loadCollective(clientId, user.account) data <- backend.clientSettings.loadCollective(
clientId,
user.account.collectiveId
)
res <- data match { res <- data match {
case Some(d) => Ok(d.settingsData) case Some(d) => Ok(d.settingsData)
case None => Ok(Map.empty[String, String]) case None => Ok(Map.empty[String, String])
@ -103,7 +114,10 @@ object ClientSettingsRoutes {
case DELETE -> Root / "collective" / Ident(clientId) => case DELETE -> Root / "collective" / Ident(clientId) =>
for { for {
flag <- backend.clientSettings.deleteCollective(clientId, user.account) flag <- backend.clientSettings.deleteCollective(
clientId,
user.account.collectiveId
)
res <- Ok( res <- Ok(
BasicResult( BasicResult(
flag, flag,

View File

@ -33,19 +33,19 @@ object CollectiveRoutes {
case GET -> Root => case GET -> Root =>
for { for {
collDb <- backend.collective.find(user.account.collective) collDb <- backend.collective.find(user.account.collective)
coll = collDb.map(c => Collective(c.id, c.state, c.created)) coll = collDb.map(c => Collective(c.name, c.state, c.created))
resp <- coll.toResponse() resp <- coll.toResponse()
} yield resp } yield resp
case GET -> Root / "insights" => case GET -> Root / "insights" =>
for { for {
ins <- backend.collective.insights(user.account.collective) ins <- backend.collective.insights(user.account.collectiveId)
resp <- Ok(Conversions.mkItemInsights(ins)) resp <- Ok(Conversions.mkItemInsights(ins))
} yield resp } yield resp
case GET -> Root / "tagcloud" => case GET -> Root / "tagcloud" =>
for { for {
cloud <- backend.collective.tagCloud(user.account.collective) cloud <- backend.collective.tagCloud(user.account.collectiveId)
resp <- Ok(Conversions.mkTagCloud(cloud)) resp <- Ok(Conversions.mkTagCloud(cloud))
} yield resp } yield resp
@ -73,13 +73,13 @@ object CollectiveRoutes {
) )
res <- res <-
backend.collective backend.collective
.updateSettings(user.account.collective, sett) .updateSettings(user.account.collectiveId, sett)
resp <- Ok(Conversions.basicResult(res, "Settings updated.")) resp <- Ok(Conversions.basicResult(res, "Settings updated."))
} yield resp } yield resp
case GET -> Root / "settings" => case GET -> Root / "settings" =>
for { for {
settDb <- backend.collective.findSettings(user.account.collective) settDb <- backend.collective.findSettings(user.account.collectiveId)
trash = settDb.flatMap(_.emptyTrash).getOrElse(OCollective.EmptyTrash.default) trash = settDb.flatMap(_.emptyTrash).getOrElse(OCollective.EmptyTrash.default)
sett = settDb.map(c => sett = settDb.map(c =>
CollectiveSettings( CollectiveSettings(
@ -108,8 +108,8 @@ object CollectiveRoutes {
for { for {
res <- res <-
backend.collective backend.collective
.getContacts(user.account.collective, q.map(_.q), kind) .getContacts(user.account.collectiveId, q.map(_.q), kind)
.take(50) .take(100)
.compile .compile
.toList .toList
resp <- Ok(ContactList(res.map(Conversions.mkContact))) resp <- Ok(ContactList(res.map(Conversions.mkContact)))
@ -117,7 +117,7 @@ object CollectiveRoutes {
case POST -> Root / "classifier" / "startonce" => case POST -> Root / "classifier" / "startonce" =>
for { for {
_ <- backend.collective.startLearnClassifier(user.account.collective) _ <- backend.collective.startLearnClassifier(user.account.collectiveId)
resp <- Ok(BasicResult(true, "Task submitted")) resp <- Ok(BasicResult(true, "Task submitted"))
} yield resp } yield resp
@ -125,11 +125,10 @@ object CollectiveRoutes {
for { for {
data <- req.as[EmptyTrashSetting] data <- req.as[EmptyTrashSetting]
_ <- backend.collective.startEmptyTrash( _ <- backend.collective.startEmptyTrash(
EmptyTrashArgs(user.account.collective, data.minAge) EmptyTrashArgs(user.account.collectiveId, data.minAge)
) )
resp <- Ok(BasicResult(true, "Task submitted")) resp <- Ok(BasicResult(true, "Task submitted"))
} yield resp } yield resp
} }
} }
} }

View File

@ -38,7 +38,7 @@ object CustomFieldRoutes {
val order = sort.getOrElse(CustomFieldOrder.NameAsc) val order = sort.getOrElse(CustomFieldOrder.NameAsc)
for { for {
fs <- backend.customFields.findAll( fs <- backend.customFields.findAll(
user.account.collective, user.account.collectiveId,
param.map(_.q), param.map(_.q),
order order
) )
@ -54,7 +54,7 @@ object CustomFieldRoutes {
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
field <- OptionT(backend.customFields.findById(user.account.collective, id)) field <- OptionT(backend.customFields.findById(user.account.collectiveId, id))
res <- OptionT.liftF(Ok(convertField(field))) res <- OptionT.liftF(Ok(convertField(field)))
} yield res).getOrElseF(NotFound(BasicResult(false, "Not found"))) } yield res).getOrElseF(NotFound(BasicResult(false, "Not found")))
@ -67,7 +67,7 @@ object CustomFieldRoutes {
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
res <- backend.customFields.delete(user.account.collective, id) res <- backend.customFields.delete(user.account.collectiveId, id)
resp <- Ok(convertResult(res)) resp <- Ok(convertResult(res))
} yield resp } yield resp
} }
@ -88,7 +88,7 @@ object CustomFieldRoutes {
id, id,
in.name, in.name,
in.label, in.label,
user.account.collective, user.account.collectiveId,
in.ftype, in.ftype,
Timestamp.Epoch Timestamp.Epoch
) )
@ -101,7 +101,7 @@ object CustomFieldRoutes {
in.name, in.name,
in.label, in.label,
in.ftype, in.ftype,
user.account.collective user.account.collectiveId
) )
private def convertField(f: CustomFieldData): CustomField = private def convertField(f: CustomFieldData): CustomField =

View File

@ -75,7 +75,7 @@ object DownloadAllRoutes {
case req @ GET -> Root / "file" / Ident(id) => case req @ GET -> Root / "file" / Ident(id) =>
for { for {
data <- backend.downloadAll.getFile(share.account.collective, id) data <- backend.downloadAll.getFile(share.account.collectiveId, id)
resp <- BinaryUtil.respond(dsl, req)(data) resp <- BinaryUtil.respond(dsl, req)(data)
} yield resp } yield resp
} }
@ -113,13 +113,13 @@ object DownloadAllRoutes {
case req @ GET -> Root / "file" / Ident(id) => case req @ GET -> Root / "file" / Ident(id) =>
for { for {
data <- backend.downloadAll.getFile(token.account.collective, id) data <- backend.downloadAll.getFile(token.account.collectiveId, id)
resp <- BinaryUtil.respond(dsl, req)(data) resp <- BinaryUtil.respond(dsl, req)(data)
} yield resp } yield resp
case HEAD -> Root / "file" / Ident(id) => case HEAD -> Root / "file" / Ident(id) =>
for { for {
data <- backend.downloadAll.getFile(token.account.collective, id) data <- backend.downloadAll.getFile(token.account.collectiveId, id)
resp <- BinaryUtil.respondHead(dsl)(data) resp <- BinaryUtil.respondHead(dsl)(data)
} yield resp } yield resp
@ -131,7 +131,7 @@ object DownloadAllRoutes {
case PUT -> Root / "cancel" / Ident(id) => case PUT -> Root / "cancel" / Ident(id) =>
for { for {
res <- backend.downloadAll.cancelDownload(token.account, id) res <- backend.downloadAll.cancelDownload(token.account.collectiveId, id)
resp <- Ok(Conversions.basicResult(res)) resp <- Ok(Conversions.basicResult(res))
} yield resp } yield resp
} }

View File

@ -33,7 +33,7 @@ object EquipmentRoutes {
case GET -> Root :? QueryParam.QueryOpt(q) :? QueryParam.EquipSort(sort) => case GET -> Root :? QueryParam.QueryOpt(q) :? QueryParam.EquipSort(sort) =>
for { for {
data <- backend.equipment.findAll( data <- backend.equipment.findAll(
user.account, user.account.collectiveId,
q.map(_.q), q.map(_.q),
sort.getOrElse(OEquipment.EquipmentOrder.NameAsc) sort.getOrElse(OEquipment.EquipmentOrder.NameAsc)
) )
@ -43,7 +43,7 @@ object EquipmentRoutes {
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[Equipment] data <- req.as[Equipment]
equip <- newEquipment(data, user.account.collective) equip <- newEquipment(data, user.account.collectiveId)
res <- backend.equipment.add(equip) res <- backend.equipment.add(equip)
resp <- Ok(basicResult(res, "Equipment created")) resp <- Ok(basicResult(res, "Equipment created"))
} yield resp } yield resp
@ -51,20 +51,20 @@ object EquipmentRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[Equipment] data <- req.as[Equipment]
equip <- changeEquipment(data, user.account.collective) equip <- changeEquipment(data, user.account.collectiveId)
res <- backend.equipment.update(equip) res <- backend.equipment.update(equip)
resp <- Ok(basicResult(res, "Equipment updated.")) resp <- Ok(basicResult(res, "Equipment updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
del <- backend.equipment.delete(id, user.account.collective) del <- backend.equipment.delete(id, user.account.collectiveId)
resp <- Ok(basicResult(del, "Equipment deleted.")) resp <- Ok(basicResult(del, "Equipment deleted."))
} yield resp } yield resp
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
equip <- OptionT(backend.equipment.find(user.account, id)) equip <- OptionT(backend.equipment.find(user.account.collectiveId, id))
resp <- OptionT.liftF(Ok(mkEquipment(equip))) resp <- OptionT.liftF(Ok(mkEquipment(equip)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
} }

View File

@ -35,9 +35,15 @@ object FolderRoutes {
QueryParam.OwningOpt(owning) +& QueryParam.FolderSort(sort) => QueryParam.OwningOpt(owning) +& QueryParam.FolderSort(sort) =>
val order = sort.getOrElse(OFolder.FolderOrder.NameAsc) val order = sort.getOrElse(OFolder.FolderOrder.NameAsc)
val login = val login =
owning.filter(identity).map(_ => user.account.user) owning.filter(identity).map(_ => user.account.login)
for { for {
all <- backend.folder.findAll(user.account, login, q.map(_.q), order) all <- backend.folder.findAll(
user.account.collectiveId,
user.account.userId,
login,
q.map(_.q),
order
)
resp <- Ok(FolderList(all.map(mkFolder).toList)) resp <- Ok(FolderList(all.map(mkFolder).toList))
} yield resp } yield resp
@ -45,46 +51,48 @@ object FolderRoutes {
for { for {
data <- req.as[NewFolder] data <- req.as[NewFolder]
nfolder <- newFolder(data, user.account) nfolder <- newFolder(data, user.account)
res <- backend.folder.add(nfolder, Some(user.account.user)) res <- backend.folder.add(nfolder, None)
resp <- resp <-
Ok(Conversions.idResult(res, nfolder.id, "Folder successfully created.")) Ok(Conversions.idResult(res, nfolder.id, "Folder successfully created."))
} yield resp } yield resp
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
folder <- OptionT(backend.folder.findById(id, user.account)) folder <- OptionT(
backend.folder.findById(id, user.account.collectiveId, user.account.userId)
)
resp <- OptionT.liftF(Ok(mkFolderDetail(folder))) resp <- OptionT.liftF(Ok(mkFolderDetail(folder)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
case req @ PUT -> Root / Ident(id) => case req @ PUT -> Root / Ident(id) =>
for { for {
data <- req.as[NewFolder] data <- req.as[NewFolder]
res <- backend.folder.changeName(id, user.account, data.name) res <- backend.folder.changeName(id, user.account.userId, data.name)
resp <- Ok(mkFolderChangeResult(res)) resp <- Ok(mkFolderChangeResult(res))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
res <- backend.folder.delete(id, user.account) res <- backend.folder.delete(id, user.account.userId)
resp <- Ok(mkFolderChangeResult(res)) resp <- Ok(mkFolderChangeResult(res))
} yield resp } yield resp
case PUT -> Root / Ident(id) / "member" / Ident(userId) => case PUT -> Root / Ident(id) / "member" / Ident(userId) =>
for { for {
res <- backend.folder.addMember(id, user.account, userId) res <- backend.folder.addMember(id, user.account.userId, userId)
resp <- Ok(mkFolderChangeResult(res)) resp <- Ok(mkFolderChangeResult(res))
} yield resp } yield resp
case DELETE -> Root / Ident(id) / "member" / Ident(userId) => case DELETE -> Root / Ident(id) / "member" / Ident(userId) =>
for { for {
res <- backend.folder.removeMember(id, user.account, userId) res <- backend.folder.removeMember(id, user.account.userId, userId)
resp <- Ok(mkFolderChangeResult(res)) resp <- Ok(mkFolderChangeResult(res))
} yield resp } yield resp
} }
} }
private def newFolder[F[_]: Sync](ns: NewFolder, account: AccountId): F[RFolder] = private def newFolder[F[_]: Sync](ns: NewFolder, account: AccountInfo): F[RFolder] =
RFolder.newFolder(ns.name, account) RFolder.newFolder(ns.name, account.collectiveId, account.userId)
private def mkFolder(item: OFolder.FolderItem): FolderItem = private def mkFolder(item: OFolder.FolderItem): FolderItem =
FolderItem( FolderItem(

View File

@ -33,7 +33,9 @@ object FullTextIndexRoutes {
HttpRoutes.of { case POST -> Root / "reIndex" => HttpRoutes.of { case POST -> Root / "reIndex" =>
for { for {
res <- backend.fulltext.reindexCollective(user.account).attempt res <- backend.fulltext
.reindexCollective(user.account.collectiveId, user.account.userId.some)
.attempt
resp <- Ok(Conversions.basicResult(res, "Full-text index will be re-created.")) resp <- Ok(Conversions.basicResult(res, "Full-text index will be re-created."))
} yield resp } yield resp
} }

View File

@ -9,14 +9,12 @@ package docspell.restserver.routes
import cats.data.{EitherT, OptionT} import cats.data.{EitherT, OptionT}
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.common._ import docspell.common._
import docspell.restserver.Config import docspell.restserver.Config
import docspell.restserver.conv.Conversions._ import docspell.restserver.conv.Conversions._
import docspell.restserver.http4s.Responses import docspell.restserver.http4s.Responses
import docspell.store.records.RItem import docspell.store.records.{RCollective, RItem}
import org.http4s._ import org.http4s._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
import org.http4s.dsl.Http4sDsl import org.http4s.dsl.Http4sDsl
@ -36,15 +34,15 @@ object IntegrationEndpointRoutes {
for { for {
_ <- authRequest(req, cfg.integrationEndpoint) _ <- authRequest(req, cfg.integrationEndpoint)
_ <- checkEnabled(cfg.integrationEndpoint) _ <- checkEnabled(cfg.integrationEndpoint)
_ <- lookupCollective(collective, backend) c <- lookupCollective(collective, backend)
} yield () } yield c
HttpRoutes.of { HttpRoutes.of {
case req @ POST -> Root / "item" / Ident(collective) => case req @ POST -> Root / "item" / Ident(collective) =>
(for { (for {
_ <- validate(req, collective) coll <- validate(req, collective)
res <- EitherT.liftF[F, Response[F], Response[F]]( res <- EitherT.liftF[F, Response[F], Response[F]](
uploadFile(collective, backend, cfg, dsl)(req) uploadFile(coll.id, backend, cfg, dsl)(req)
) )
} yield res).fold(identity, identity) } yield res).fold(identity, identity)
@ -56,9 +54,9 @@ object IntegrationEndpointRoutes {
case req @ GET -> Root / "checkfile" / Ident(collective) / checksum => case req @ GET -> Root / "checkfile" / Ident(collective) / checksum =>
(for { (for {
_ <- validate(req, collective) coll <- validate(req, collective)
items <- EitherT.liftF[F, Response[F], Vector[RItem]]( items <- EitherT.liftF[F, Response[F], Vector[RItem]](
backend.itemSearch.findByFileCollective(checksum, collective) backend.itemSearch.findByFileCollective(checksum, coll.id)
) )
resp <- resp <-
EitherT.liftF[F, Response[F], Response[F]](Ok(CheckFileRoutes.convert(items))) EitherT.liftF[F, Response[F], Response[F]](Ok(CheckFileRoutes.convert(items)))
@ -86,14 +84,13 @@ object IntegrationEndpointRoutes {
def lookupCollective[F[_]: Async]( def lookupCollective[F[_]: Async](
coll: Ident, coll: Ident,
backend: BackendApp[F] backend: BackendApp[F]
): EitherT[F, Response[F], Unit] = ): EitherT[F, Response[F], RCollective] =
for { OptionT(backend.collective.find(coll))
opt <- EitherT.liftF(backend.collective.find(coll)) .filter(_.integrationEnabled)
res <- EitherT.cond[F](opt.exists(_.integrationEnabled), (), Response.notFound[F]) .toRight(Response.notFound[F])
} yield res
def uploadFile[F[_]: Async]( def uploadFile[F[_]: Async](
coll: Ident, cid: CollectiveId,
backend: BackendApp[F], backend: BackendApp[F],
cfg: Config, cfg: Config,
dsl: Http4sDsl[F] dsl: Http4sDsl[F]
@ -110,8 +107,7 @@ object IntegrationEndpointRoutes {
cfg.integrationEndpoint.priority, cfg.integrationEndpoint.priority,
cfg.backend.files.validMimeTypes cfg.backend.files.validMimeTypes
) )
account = AccountId(coll, DocspellSystem.user) result <- backend.upload.submit(updata, cid, None, None)
result <- backend.upload.submit(updata, account, None)
res <- Ok(basicResult(result)) res <- Ok(basicResult(result))
} yield res } yield res
} }

View File

@ -22,7 +22,7 @@ import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityCodec._ import org.http4s.circe.CirceEntityCodec._
import org.http4s.dsl.Http4sDsl import org.http4s.dsl.Http4sDsl
class ItemLinkRoutes[F[_]: Async](account: AccountId, backend: OItemLink[F]) class ItemLinkRoutes[F[_]: Async](account: AccountInfo, backend: OItemLink[F])
extends Http4sDsl[F] { extends Http4sDsl[F] {
def get: HttpRoutes[F] = def get: HttpRoutes[F] =
HttpRoutes.of { HttpRoutes.of {
@ -36,7 +36,7 @@ class ItemLinkRoutes[F[_]: Async](account: AccountId, backend: OItemLink[F])
case DELETE -> Root / Ident(target) / Ident(id) => case DELETE -> Root / Ident(target) / Ident(id) =>
for { for {
_ <- backend.removeAll(account.collective, target, NonEmptyList.of(id)) _ <- backend.removeAll(account.collectiveId, target, NonEmptyList.of(id))
resp <- Ok(BasicResult(true, "Related items removed")) resp <- Ok(BasicResult(true, "Related items removed"))
} yield resp } yield resp
@ -46,7 +46,7 @@ class ItemLinkRoutes[F[_]: Async](account: AccountId, backend: OItemLink[F])
related = NonEmptyList.fromList(input.related) related = NonEmptyList.fromList(input.related)
res <- OptionT res <- OptionT
.fromOption[F](related) .fromOption[F](related)
.semiflatMap(backend.addAll(account.collective, input.item, _)) .semiflatMap(backend.addAll(account.collectiveId, input.item, _))
.value .value
resp <- Ok(convertResult(res)) resp <- Ok(convertResult(res))
} yield resp } yield resp
@ -56,7 +56,7 @@ class ItemLinkRoutes[F[_]: Async](account: AccountId, backend: OItemLink[F])
input <- req.as[ItemLinkData] input <- req.as[ItemLinkData]
related = NonEmptyList.fromList(input.related) related = NonEmptyList.fromList(input.related)
_ <- related _ <- related
.map(backend.removeAll(account.collective, input.item, _)) .map(backend.removeAll(account.collectiveId, input.item, _))
.getOrElse( .getOrElse(
BadRequest(BasicResult(false, "List of related items must not be empty")) BadRequest(BasicResult(false, "List of related items must not be empty"))
) )
@ -77,6 +77,6 @@ class ItemLinkRoutes[F[_]: Async](account: AccountId, backend: OItemLink[F])
object ItemLinkRoutes { object ItemLinkRoutes {
def apply[F[_]: Async](account: AccountId, itemLink: OItemLink[F]): HttpRoutes[F] = def apply[F[_]: Async](account: AccountInfo, itemLink: OItemLink[F]): HttpRoutes[F] =
new ItemLinkRoutes[F](account, itemLink).get new ItemLinkRoutes[F](account, itemLink).get
} }

View File

@ -8,7 +8,6 @@ package docspell.restserver.routes
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.backend.ops.OCustomFields.{RemoveValue, SetValue} import docspell.backend.ops.OCustomFields.{RemoveValue, SetValue}
@ -17,7 +16,7 @@ import docspell.restapi.model._
import docspell.restserver.Config import docspell.restserver.Config
import docspell.restserver.conv.{Conversions, MultiIdSupport, NonEmptyListSupport} import docspell.restserver.conv.{Conversions, MultiIdSupport, NonEmptyListSupport}
import docspell.restserver.http4s.ClientRequestInfo import docspell.restserver.http4s.ClientRequestInfo
import docspell.scheduler.usertask.UserTaskScope
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
@ -42,7 +41,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.setStates( res <- backend.item.setStates(
data, data,
ItemState.Confirmed, ItemState.Confirmed,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Item data confirmed")) resp <- Ok(Conversions.basicResult(res, "Item data confirmed"))
} yield resp } yield resp
@ -54,7 +53,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.setStates( res <- backend.item.setStates(
data, data,
ItemState.Created, ItemState.Created,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Item back to created.")) resp <- Ok(Conversions.basicResult(res, "Item back to created."))
} yield resp } yield resp
@ -66,7 +65,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.setTagsMultipleItems( res <- backend.item.setTagsMultipleItems(
items, items,
json.refs, json.refs,
user.account.collective user.account.collectiveId
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -80,7 +79,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.linkTagsMultipleItems( res <- backend.item.linkTagsMultipleItems(
items, items,
json.refs, json.refs,
user.account.collective user.account.collectiveId
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -94,7 +93,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.removeTagsMultipleItems( res <- backend.item.removeTagsMultipleItems(
items, items,
json.refs, json.refs,
user.account.collective user.account.collectiveId
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -108,7 +107,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.setNameMultiple( res <- backend.item.setNameMultiple(
items, items,
json.name.notEmpty.getOrElse(""), json.name.notEmpty.getOrElse(""),
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Name updated")) resp <- Ok(Conversions.basicResult(res, "Name updated"))
} yield resp } yield resp
@ -120,7 +119,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
res <- backend.item.setFolderMultiple( res <- backend.item.setFolderMultiple(
items, items,
json.ref.map(_.id), json.ref.map(_.id),
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Folder updated")) resp <- Ok(Conversions.basicResult(res, "Folder updated"))
} yield resp } yield resp
@ -129,7 +128,11 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndDirection] json <- req.as[ItemsAndDirection]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setDirection(items, json.direction, user.account.collective) res <- backend.item.setDirection(
items,
json.direction,
user.account.collectiveId
)
resp <- Ok(Conversions.basicResult(res, "Direction updated")) resp <- Ok(Conversions.basicResult(res, "Direction updated"))
} yield resp } yield resp
@ -137,7 +140,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndDate] json <- req.as[ItemsAndDate]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setItemDate(items, json.date, user.account.collective) res <- backend.item.setItemDate(items, json.date, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Item date updated")) resp <- Ok(Conversions.basicResult(res, "Item date updated"))
} yield resp } yield resp
@ -145,7 +148,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndDate] json <- req.as[ItemsAndDate]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setItemDueDate(items, json.date, user.account.collective) res <- backend.item.setItemDueDate(items, json.date, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Item due date updated")) resp <- Ok(Conversions.basicResult(res, "Item due date updated"))
} yield resp } yield resp
@ -153,7 +156,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndRef] json <- req.as[ItemsAndRef]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setCorrOrg(items, json.ref, user.account.collective) res <- backend.item.setCorrOrg(items, json.ref, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated"))
} yield resp } yield resp
@ -161,7 +164,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndRef] json <- req.as[ItemsAndRef]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setCorrPerson(items, json.ref, user.account.collective) res <- backend.item.setCorrPerson(items, json.ref, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent person updated"))
} yield resp } yield resp
@ -169,7 +172,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndRef] json <- req.as[ItemsAndRef]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setConcPerson(items, json.ref, user.account.collective) res <- backend.item.setConcPerson(items, json.ref, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) resp <- Ok(Conversions.basicResult(res, "Concerned person updated"))
} yield resp } yield resp
@ -177,7 +180,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[ItemsAndRef] json <- req.as[ItemsAndRef]
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.item.setConcEquip(items, json.ref, user.account.collective) res <- backend.item.setConcEquip(items, json.ref, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
} yield resp } yield resp
@ -185,7 +188,11 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[IdList] json <- req.as[IdList]
items <- requireNonEmpty(json.ids) items <- requireNonEmpty(json.ids)
res <- backend.item.reprocessAll(items, user.account) res <- backend.item.reprocessAll(
user.account.collectiveId,
items,
UserTaskScope(user.account)
)
resp <- Ok(Conversions.basicResult(res, "Re-process task(s) submitted.")) resp <- Ok(Conversions.basicResult(res, "Re-process task(s) submitted."))
} yield resp } yield resp
@ -193,7 +200,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[IdList] json <- req.as[IdList]
items <- requireNonEmpty(json.ids) items <- requireNonEmpty(json.ids)
n <- backend.item.setDeletedState(items, user.account.collective) n <- backend.item.setDeletedState(items, user.account.collectiveId)
res = BasicResult( res = BasicResult(
n > 0, n > 0,
if (n > 0) "Item(s) deleted" else "Item deletion failed." if (n > 0) "Item(s) deleted" else "Item deletion failed."
@ -205,7 +212,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[IdList] json <- req.as[IdList]
items <- requireNonEmpty(json.ids) items <- requireNonEmpty(json.ids)
res <- backend.item.restore(items, user.account.collective) res <- backend.item.restore(items, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Item(s) deleted")) resp <- Ok(Conversions.basicResult(res, "Item(s) deleted"))
} yield resp } yield resp
@ -215,7 +222,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
res <- backend.customFields.setValueMultiple( res <- backend.customFields.setValueMultiple(
items, items,
SetValue(json.field.field, json.field.value, user.account.collective) SetValue(json.field.field, json.field.value, user.account.collectiveId)
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -228,7 +235,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
items <- requireNonEmpty(json.items) items <- requireNonEmpty(json.items)
field <- readId[F](json.name) field <- readId[F](json.name)
res <- backend.customFields.deleteValue( res <- backend.customFields.deleteValue(
RemoveValue(field, items, user.account.collective) RemoveValue(field, items, user.account.collectiveId)
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -239,7 +246,7 @@ object ItemMultiRoutes extends NonEmptyListSupport with MultiIdSupport {
for { for {
json <- req.as[IdList] json <- req.as[IdList]
items <- requireNonEmpty(json.ids) items <- requireNonEmpty(json.ids)
res <- backend.item.merge(logger, items, user.account.collective) res <- backend.item.merge(logger, items, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Items merged")) resp <- Ok(Conversions.basicResult(res, "Items merged"))
} yield resp } yield resp
} }

View File

@ -9,7 +9,6 @@ package docspell.restserver.routes
import cats.data.NonEmptyList import cats.data.NonEmptyList
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.backend.ops.OCustomFields.{RemoveValue, SetValue} import docspell.backend.ops.OCustomFields.{RemoveValue, SetValue}
@ -21,7 +20,7 @@ import docspell.restserver.http4s.BinaryUtil
import docspell.restserver.http4s.ClientRequestInfo import docspell.restserver.http4s.ClientRequestInfo
import docspell.restserver.http4s.Responses import docspell.restserver.http4s.Responses
import docspell.restserver.http4s.{QueryParam => QP} import docspell.restserver.http4s.{QueryParam => QP}
import docspell.scheduler.usertask.UserTaskScope
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
@ -43,7 +42,7 @@ object ItemRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
for { for {
item <- backend.itemSearch.findItem(id, user.account.collective) item <- backend.itemSearch.findItem(id, user.account.collectiveId)
result = item.map(Conversions.mkItemDetail) result = item.map(Conversions.mkItemDetail)
resp <- resp <-
result result
@ -53,26 +52,30 @@ object ItemRoutes {
case POST -> Root / Ident(id) / "confirm" => case POST -> Root / Ident(id) / "confirm" =>
for { for {
res <- backend.item.setState(id, ItemState.Confirmed, user.account.collective) res <- backend.item.setState(
id,
ItemState.Confirmed,
user.account.collectiveId
)
resp <- Ok(Conversions.basicResult(res, "Item data confirmed")) resp <- Ok(Conversions.basicResult(res, "Item data confirmed"))
} yield resp } yield resp
case POST -> Root / Ident(id) / "unconfirm" => case POST -> Root / Ident(id) / "unconfirm" =>
for { for {
res <- backend.item.setState(id, ItemState.Created, user.account.collective) res <- backend.item.setState(id, ItemState.Created, user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Item back to created.")) resp <- Ok(Conversions.basicResult(res, "Item back to created."))
} yield resp } yield resp
case POST -> Root / Ident(id) / "restore" => case POST -> Root / Ident(id) / "restore" =>
for { for {
res <- backend.item.restore(NonEmptyList.of(id), user.account.collective) res <- backend.item.restore(NonEmptyList.of(id), user.account.collectiveId)
resp <- Ok(Conversions.basicResult(res, "Item restored.")) resp <- Ok(Conversions.basicResult(res, "Item restored."))
} yield resp } yield resp
case req @ PUT -> Root / Ident(id) / "tags" => case req @ PUT -> Root / Ident(id) / "tags" =>
for { for {
tags <- req.as[StringList].map(_.items) tags <- req.as[StringList].map(_.items)
res <- backend.item.setTags(id, tags, user.account.collective) res <- backend.item.setTags(id, tags, user.account.collectiveId)
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
resp <- Ok(Conversions.basicResult(res.value, "Tags updated")) resp <- Ok(Conversions.basicResult(res.value, "Tags updated"))
@ -81,8 +84,8 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "tags" => case req @ POST -> Root / Ident(id) / "tags" =>
for { for {
data <- req.as[Tag] data <- req.as[Tag]
rtag <- Conversions.newTag(data, user.account.collective) rtag <- Conversions.newTag(data, user.account.collectiveId)
res <- backend.item.addNewTag(user.account.collective, id, rtag) res <- backend.item.addNewTag(user.account.collectiveId, id, rtag)
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
resp <- Ok(Conversions.basicResult(res.value, "Tag added.")) resp <- Ok(Conversions.basicResult(res.value, "Tag added."))
@ -91,7 +94,7 @@ object ItemRoutes {
case req @ PUT -> Root / Ident(id) / "taglink" => case req @ PUT -> Root / Ident(id) / "taglink" =>
for { for {
tags <- req.as[StringList] tags <- req.as[StringList]
res <- backend.item.linkTags(id, tags.items, user.account.collective) res <- backend.item.linkTags(id, tags.items, user.account.collectiveId)
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
resp <- Ok(Conversions.basicResult(res.value, "Tags linked")) resp <- Ok(Conversions.basicResult(res.value, "Tags linked"))
@ -100,7 +103,7 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "tagtoggle" => case req @ POST -> Root / Ident(id) / "tagtoggle" =>
for { for {
tags <- req.as[StringList] tags <- req.as[StringList]
res <- backend.item.toggleTags(id, tags.items, user.account.collective) res <- backend.item.toggleTags(id, tags.items, user.account.collectiveId)
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
resp <- Ok(Conversions.basicResult(res.value, "Tags linked")) resp <- Ok(Conversions.basicResult(res.value, "Tags linked"))
@ -112,7 +115,7 @@ object ItemRoutes {
res <- backend.item.removeTagsMultipleItems( res <- backend.item.removeTagsMultipleItems(
NonEmptyList.of(id), NonEmptyList.of(id),
json.items, json.items,
user.account.collective user.account.collectiveId
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -125,7 +128,7 @@ object ItemRoutes {
res <- backend.item.setDirection( res <- backend.item.setDirection(
NonEmptyList.of(id), NonEmptyList.of(id),
dir.direction, dir.direction,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Direction updated")) resp <- Ok(Conversions.basicResult(res, "Direction updated"))
} yield resp } yield resp
@ -133,7 +136,11 @@ object ItemRoutes {
case req @ PUT -> Root / Ident(id) / "folder" => case req @ PUT -> Root / Ident(id) / "folder" =>
for { for {
idref <- req.as[OptionalId] idref <- req.as[OptionalId]
res <- backend.item.setFolder(id, idref.id.map(_.id), user.account.collective) res <- backend.item.setFolder(
id,
idref.id.map(_.id),
user.account.collectiveId
)
resp <- Ok(Conversions.basicResult(res, "Folder updated")) resp <- Ok(Conversions.basicResult(res, "Folder updated"))
} yield resp } yield resp
@ -143,7 +150,7 @@ object ItemRoutes {
res <- backend.item.setCorrOrg( res <- backend.item.setCorrOrg(
NonEmptyList.of(id), NonEmptyList.of(id),
idref.id, idref.id,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated"))
} yield resp } yield resp
@ -151,7 +158,7 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "corrOrg" => case req @ POST -> Root / Ident(id) / "corrOrg" =>
for { for {
data <- req.as[Organization] data <- req.as[Organization]
org <- Conversions.newOrg(data, user.account.collective) org <- Conversions.newOrg(data, user.account.collectiveId)
res <- backend.item.addCorrOrg(id, org) res <- backend.item.addCorrOrg(id, org)
resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated"))
} yield resp } yield resp
@ -162,7 +169,7 @@ object ItemRoutes {
res <- backend.item.setCorrPerson( res <- backend.item.setCorrPerson(
NonEmptyList.of(id), NonEmptyList.of(id),
idref.id, idref.id,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent person updated"))
} yield resp } yield resp
@ -170,7 +177,7 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "corrPerson" => case req @ POST -> Root / Ident(id) / "corrPerson" =>
for { for {
data <- req.as[Person] data <- req.as[Person]
pers <- Conversions.newPerson(data, user.account.collective) pers <- Conversions.newPerson(data, user.account.collectiveId)
res <- backend.item.addCorrPerson(id, pers) res <- backend.item.addCorrPerson(id, pers)
resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) resp <- Ok(Conversions.basicResult(res, "Correspondent person updated"))
} yield resp } yield resp
@ -181,7 +188,7 @@ object ItemRoutes {
res <- backend.item.setConcPerson( res <- backend.item.setConcPerson(
NonEmptyList.of(id), NonEmptyList.of(id),
idref.id, idref.id,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) resp <- Ok(Conversions.basicResult(res, "Concerned person updated"))
} yield resp } yield resp
@ -189,7 +196,7 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "concPerson" => case req @ POST -> Root / Ident(id) / "concPerson" =>
for { for {
data <- req.as[Person] data <- req.as[Person]
pers <- Conversions.newPerson(data, user.account.collective) pers <- Conversions.newPerson(data, user.account.collectiveId)
res <- backend.item.addConcPerson(id, pers) res <- backend.item.addConcPerson(id, pers)
resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) resp <- Ok(Conversions.basicResult(res, "Concerned person updated"))
} yield resp } yield resp
@ -200,7 +207,7 @@ object ItemRoutes {
res <- backend.item.setConcEquip( res <- backend.item.setConcEquip(
NonEmptyList.of(id), NonEmptyList.of(id),
idref.id, idref.id,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
} yield resp } yield resp
@ -208,7 +215,7 @@ object ItemRoutes {
case req @ POST -> Root / Ident(id) / "concEquipment" => case req @ POST -> Root / Ident(id) / "concEquipment" =>
for { for {
data <- req.as[Equipment] data <- req.as[Equipment]
equip <- Conversions.newEquipment(data, user.account.collective) equip <- Conversions.newEquipment(data, user.account.collectiveId)
res <- backend.item.addConcEquip(id, equip) res <- backend.item.addConcEquip(id, equip)
resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated"))
} yield resp } yield resp
@ -216,7 +223,11 @@ object ItemRoutes {
case req @ PUT -> Root / Ident(id) / "notes" => case req @ PUT -> Root / Ident(id) / "notes" =>
for { for {
text <- req.as[OptionalText] text <- req.as[OptionalText]
res <- backend.item.setNotes(id, text.text.notEmpty, user.account.collective) res <- backend.item.setNotes(
id,
text.text.notEmpty,
user.account.collectiveId
)
resp <- Ok(Conversions.basicResult(res, "Notes updated")) resp <- Ok(Conversions.basicResult(res, "Notes updated"))
} yield resp } yield resp
@ -226,7 +237,7 @@ object ItemRoutes {
res <- backend.item.setName( res <- backend.item.setName(
id, id,
text.text.notEmpty.getOrElse(""), text.text.notEmpty.getOrElse(""),
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Name updated")) resp <- Ok(Conversions.basicResult(res, "Name updated"))
} yield resp } yield resp
@ -238,7 +249,7 @@ object ItemRoutes {
res <- backend.item.setItemDueDate( res <- backend.item.setItemDueDate(
NonEmptyList.of(id), NonEmptyList.of(id),
date.date, date.date,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Item due date updated")) resp <- Ok(Conversions.basicResult(res, "Item due date updated"))
} yield resp } yield resp
@ -250,14 +261,14 @@ object ItemRoutes {
res <- backend.item.setItemDate( res <- backend.item.setItemDate(
NonEmptyList.of(id), NonEmptyList.of(id),
date.date, date.date,
user.account.collective user.account.collectiveId
) )
resp <- Ok(Conversions.basicResult(res, "Item date updated")) resp <- Ok(Conversions.basicResult(res, "Item date updated"))
} yield resp } yield resp
case GET -> Root / Ident(id) / "proposals" => case GET -> Root / Ident(id) / "proposals" =>
for { for {
ml <- backend.item.getProposals(id, user.account.collective) ml <- backend.item.getProposals(id, user.account.collectiveId)
ip = Conversions.mkItemProposals(ml) ip = Conversions.mkItemProposals(ml)
resp <- Ok(ip) resp <- Ok(ip)
} yield resp } yield resp
@ -274,7 +285,7 @@ object ItemRoutes {
def notFound = def notFound =
NotFound(BasicResult(false, "Not found")) NotFound(BasicResult(false, "Not found"))
for { for {
preview <- backend.itemSearch.findItemPreview(id, user.account.collective) preview <- backend.itemSearch.findItemPreview(id, user.account.collectiveId)
inm = req.headers.get[`If-None-Match`].flatMap(_.tags) inm = req.headers.get[`If-None-Match`].flatMap(_.tags)
matches = BinaryUtil.matchETag(preview.map(_.meta), inm) matches = BinaryUtil.matchETag(preview.map(_.meta), inm)
fallback = flag.getOrElse(false) fallback = flag.getOrElse(false)
@ -292,7 +303,7 @@ object ItemRoutes {
case HEAD -> Root / Ident(id) / "preview" => case HEAD -> Root / Ident(id) / "preview" =>
for { for {
preview <- backend.itemSearch.findItemPreview(id, user.account.collective) preview <- backend.itemSearch.findItemPreview(id, user.account.collectiveId)
resp <- resp <-
preview preview
.map(data => BinaryUtil.withResponseHeaders(dsl, Ok())(data)) .map(data => BinaryUtil.withResponseHeaders(dsl, Ok())(data))
@ -303,7 +314,12 @@ object ItemRoutes {
for { for {
data <- req.as[IdList] data <- req.as[IdList]
_ <- logger.debug(s"Re-process item ${id.id}") _ <- logger.debug(s"Re-process item ${id.id}")
res <- backend.item.reprocess(id, data.ids, user.account) res <- backend.item.reprocess(
user.account.collectiveId,
id,
data.ids,
UserTaskScope(user.account)
)
resp <- Ok(Conversions.basicResult(res, "Re-process task submitted.")) resp <- Ok(Conversions.basicResult(res, "Re-process task submitted."))
} yield resp } yield resp
@ -312,7 +328,7 @@ object ItemRoutes {
data <- req.as[CustomFieldValue] data <- req.as[CustomFieldValue]
res <- backend.customFields.setValue( res <- backend.customFields.setValue(
id, id,
SetValue(data.field, data.value, user.account.collective) SetValue(data.field, data.value, user.account.collectiveId)
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -322,7 +338,7 @@ object ItemRoutes {
case req @ DELETE -> Root / Ident(id) / "customfield" / Ident(fieldId) => case req @ DELETE -> Root / Ident(id) / "customfield" / Ident(fieldId) =>
for { for {
res <- backend.customFields.deleteValue( res <- backend.customFields.deleteValue(
RemoveValue(fieldId, NonEmptyList.of(id), user.account.collective) RemoveValue(fieldId, NonEmptyList.of(id), user.account.collectiveId)
) )
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
_ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some))
@ -333,7 +349,7 @@ object ItemRoutes {
for { for {
n <- backend.item.setDeletedState( n <- backend.item.setDeletedState(
NonEmptyList.of(id), NonEmptyList.of(id),
user.account.collective user.account.collectiveId
) )
res = BasicResult( res = BasicResult(
n > 0, n > 0,

View File

@ -8,13 +8,12 @@ package docspell.restserver.routes
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.common.Ident import docspell.common.Ident
import docspell.restapi.model.JobPriority import docspell.restapi.model.JobPriority
import docspell.restserver.conv.Conversions import docspell.restserver.conv.Conversions
import docspell.scheduler.usertask.UserTaskScope
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
@ -29,21 +28,21 @@ object JobQueueRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root / "state" => case GET -> Root / "state" =>
for { for {
js <- backend.job.queueState(user.account.collective, 40) js <- backend.job.queueState(UserTaskScope(user.account), 40)
res = Conversions.mkJobQueueState(js) res = Conversions.mkJobQueueState(js)
resp <- Ok(res) resp <- Ok(res)
} yield resp } yield resp
case POST -> Root / Ident(id) / "cancel" => case POST -> Root / Ident(id) / "cancel" =>
for { for {
result <- backend.job.cancelJob(id, user.account.collective) result <- backend.job.cancelJob(id, UserTaskScope(user.account))
resp <- Ok(Conversions.basicResult(result)) resp <- Ok(Conversions.basicResult(result))
} yield resp } yield resp
case req @ POST -> Root / Ident(id) / "priority" => case req @ POST -> Root / Ident(id) / "priority" =>
for { for {
prio <- req.as[JobPriority] prio <- req.as[JobPriority]
res <- backend.job.setPriority(id, user.account.collective, prio.priority) res <- backend.job.setPriority(id, UserTaskScope(user.account), prio.priority)
resp <- Ok(Conversions.basicResult(res, "Job priority changed")) resp <- Ok(Conversions.basicResult(res, "Job priority changed"))
} yield resp } yield resp
} }

View File

@ -96,7 +96,7 @@ object LoginRoutes {
resp <- Ok( resp <- Ok(
AuthResult( AuthResult(
token.account.collective.id, token.account.collective.id,
token.account.user.id, token.account.login.id,
true, true,
"Login successful", "Login successful",
Some(cd.asString), Some(cd.asString),

View File

@ -32,7 +32,9 @@ object MailSendRoutes {
for { for {
in <- req.as[SimpleMail] in <- req.as[SimpleMail]
mail = convertIn(id, in) mail = convertIn(id, in)
res <- mail.traverse(m => backend.mail.sendMail(user.account, name, m)) res <- mail.traverse(m =>
backend.mail.sendMail(user.account.userId, user.account.collectiveId, name, m)
)
resp <- res.fold( resp <- res.fold(
err => Ok(BasicResult(false, s"Invalid mail data: $err")), err => Ok(BasicResult(false, s"Invalid mail data: $err")),
res => Ok(convertOut(res)) res => Ok(convertOut(res))

View File

@ -35,27 +35,27 @@ object MailSettingsRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root / "smtp" :? QueryParam.QueryOpt(q) => case GET -> Root / "smtp" :? QueryParam.QueryOpt(q) =>
for { for {
list <- backend.mail.getSmtpSettings(user.account, q.map(_.q)) list <- backend.mail.getSmtpSettings(user.account.userId, q.map(_.q))
res = list.map(convert) res = list.map(convert)
resp <- Ok(EmailSettingsList(res.toList)) resp <- Ok(EmailSettingsList(res.toList))
} yield resp } yield resp
case GET -> Root / "imap" :? QueryParam.QueryOpt(q) => case GET -> Root / "imap" :? QueryParam.QueryOpt(q) =>
for { for {
list <- backend.mail.getImapSettings(user.account, q.map(_.q)) list <- backend.mail.getImapSettings(user.account.userId, q.map(_.q))
res = list.map(convert) res = list.map(convert)
resp <- Ok(ImapSettingsList(res.toList)) resp <- Ok(ImapSettingsList(res.toList))
} yield resp } yield resp
case GET -> Root / "smtp" / Ident(name) => case GET -> Root / "smtp" / Ident(name) =>
(for { (for {
ems <- backend.mail.findSmtpSettings(user.account, name) ems <- backend.mail.findSmtpSettings(user.account.userId, name)
resp <- OptionT.liftF(Ok(convert(ems))) resp <- OptionT.liftF(Ok(convert(ems)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
case GET -> Root / "imap" / Ident(name) => case GET -> Root / "imap" / Ident(name) =>
(for { (for {
ems <- backend.mail.findImapSettings(user.account, name) ems <- backend.mail.findImapSettings(user.account.userId, name)
resp <- OptionT.liftF(Ok(convert(ems))) resp <- OptionT.liftF(Ok(convert(ems)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
@ -64,7 +64,7 @@ object MailSettingsRoutes {
in <- OptionT.liftF(req.as[EmailSettings]) in <- OptionT.liftF(req.as[EmailSettings])
ru = makeSmtpSettings(in) ru = makeSmtpSettings(in)
up <- OptionT.liftF( up <- OptionT.liftF(
ru.traverse(r => backend.mail.createSmtpSettings(user.account, r)) ru.traverse(r => backend.mail.createSmtpSettings(user.account.userId, r))
) )
resp <- OptionT.liftF( resp <- OptionT.liftF(
Ok( Ok(
@ -81,7 +81,7 @@ object MailSettingsRoutes {
in <- OptionT.liftF(req.as[ImapSettings]) in <- OptionT.liftF(req.as[ImapSettings])
ru = makeImapSettings(in) ru = makeImapSettings(in)
up <- OptionT.liftF( up <- OptionT.liftF(
ru.traverse(r => backend.mail.createImapSettings(user.account, r)) ru.traverse(r => backend.mail.createImapSettings(user.account.userId, r))
) )
resp <- OptionT.liftF( resp <- OptionT.liftF(
Ok( Ok(
@ -98,7 +98,9 @@ object MailSettingsRoutes {
in <- OptionT.liftF(req.as[EmailSettings]) in <- OptionT.liftF(req.as[EmailSettings])
ru = makeSmtpSettings(in) ru = makeSmtpSettings(in)
up <- OptionT.liftF( up <- OptionT.liftF(
ru.traverse(r => backend.mail.updateSmtpSettings(user.account, name, r)) ru.traverse(r =>
backend.mail.updateSmtpSettings(user.account.userId, name, r)
)
) )
resp <- OptionT.liftF( resp <- OptionT.liftF(
Ok( Ok(
@ -117,7 +119,9 @@ object MailSettingsRoutes {
in <- OptionT.liftF(req.as[ImapSettings]) in <- OptionT.liftF(req.as[ImapSettings])
ru = makeImapSettings(in) ru = makeImapSettings(in)
up <- OptionT.liftF( up <- OptionT.liftF(
ru.traverse(r => backend.mail.updateImapSettings(user.account, name, r)) ru.traverse(r =>
backend.mail.updateImapSettings(user.account.userId, name, r)
)
) )
resp <- OptionT.liftF( resp <- OptionT.liftF(
Ok( Ok(
@ -133,7 +137,7 @@ object MailSettingsRoutes {
case DELETE -> Root / "smtp" / Ident(name) => case DELETE -> Root / "smtp" / Ident(name) =>
for { for {
n <- backend.mail.deleteSmtpSettings(user.account, name) n <- backend.mail.deleteSmtpSettings(user.account.userId, name)
resp <- Ok( resp <- Ok(
if (n > 0) BasicResult(true, "Mail settings removed") if (n > 0) BasicResult(true, "Mail settings removed")
else BasicResult(false, "Mail settings could not be removed") else BasicResult(false, "Mail settings could not be removed")
@ -142,7 +146,7 @@ object MailSettingsRoutes {
case DELETE -> Root / "imap" / Ident(name) => case DELETE -> Root / "imap" / Ident(name) =>
for { for {
n <- backend.mail.deleteImapSettings(user.account, name) n <- backend.mail.deleteImapSettings(user.account.userId, name)
resp <- Ok( resp <- Ok(
if (n > 0) BasicResult(true, "Mail settings removed") if (n > 0) BasicResult(true, "Mail settings removed")
else BasicResult(false, "Mail settings could not be removed") else BasicResult(false, "Mail settings could not be removed")

View File

@ -50,14 +50,14 @@ object NotificationRoutes extends NonEmptyListSupport {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
for { for {
list <- backend.notification.listChannels(user.account) list <- backend.notification.listChannels(user.account.userId)
data = list.map(NotificationChannel.convert) data = list.map(NotificationChannel.convert)
resp <- Ok(data) resp <- Ok(data)
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
res <- backend.notification.deleteChannel(id, user.account) res <- backend.notification.deleteChannel(id, user.account.userId)
resp <- Ok(Conversions.basicResult(res, "Channel deleted")) resp <- Ok(Conversions.basicResult(res, "Channel deleted"))
} yield resp } yield resp
@ -69,7 +69,7 @@ object NotificationRoutes extends NonEmptyListSupport {
.fromEither[F](ch) .fromEither[F](ch)
.semiflatMap { c => .semiflatMap { c =>
backend.notification backend.notification
.createChannel(c, user.account) .createChannel(c, user.account.userId)
.map(res => Conversions.basicResult(res, "Channel created")) .map(res => Conversions.basicResult(res, "Channel created"))
} }
.foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_)) .foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_))
@ -83,7 +83,7 @@ object NotificationRoutes extends NonEmptyListSupport {
.fromEither[F](ch) .fromEither[F](ch)
.semiflatMap { c => .semiflatMap { c =>
backend.notification backend.notification
.updateChannel(c, user.account) .updateChannel(c, user.account.userId)
.map(res => Conversions.basicResult(res, "Channel created")) .map(res => Conversions.basicResult(res, "Channel created"))
} }
.foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_)) .foldF(ex => BadRequest(BasicResult(false, ex.getMessage)), Ok(_))
@ -102,14 +102,14 @@ object NotificationRoutes extends NonEmptyListSupport {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
for { for {
list <- backend.notification.listHooks(user.account) list <- backend.notification.listHooks(user.account.userId)
data = list.map(Converters.convertHook) data = list.map(Converters.convertHook)
resp <- Ok(data) resp <- Ok(data)
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
res <- backend.notification.deleteHook(id, user.account) res <- backend.notification.deleteHook(id, user.account.userId)
resp <- Ok(Conversions.basicResult(res, "Hook deleted.")) resp <- Ok(Conversions.basicResult(res, "Hook deleted."))
} yield resp } yield resp
@ -117,7 +117,7 @@ object NotificationRoutes extends NonEmptyListSupport {
for { for {
input <- req.as[NotificationHook] input <- req.as[NotificationHook]
hook <- Sync[F].pure(Converters.convertHook(input)).rethrow hook <- Sync[F].pure(Converters.convertHook(input)).rethrow
res <- backend.notification.createHook(hook, user.account) res <- backend.notification.createHook(hook, user.account.userId)
resp <- Ok(Conversions.basicResult(res, "Hook created")) resp <- Ok(Conversions.basicResult(res, "Hook created"))
} yield resp } yield resp
@ -125,7 +125,7 @@ object NotificationRoutes extends NonEmptyListSupport {
for { for {
input <- req.as[NotificationHook] input <- req.as[NotificationHook]
hook <- Sync[F].pure(Converters.convertHook(input)).rethrow hook <- Sync[F].pure(Converters.convertHook(input)).rethrow
res <- backend.notification.updateHook(hook, user.account) res <- backend.notification.updateHook(hook, user.account.userId)
resp <- Ok(Conversions.basicResult(res, "Hook updated")) resp <- Ok(Conversions.basicResult(res, "Hook updated"))
} yield resp } yield resp
@ -187,7 +187,7 @@ object NotificationRoutes extends NonEmptyListSupport {
NotificationHook( NotificationHook(
h.id, h.id,
h.enabled, h.enabled,
h.channels.map(c => NotificationChannelRef(c.id, c.channelType, c.name)).toList, h.channels.map(c => NotificationChannelRef(c.id, c.channelType, c.name)),
h.allEvents, h.allEvents,
h.eventFilter, h.eventFilter,
h.events h.events

View File

@ -110,7 +110,7 @@ object NotifyDueItemsRoutes extends MailAddressCodec with NonEmptyListSupport {
def makeTask[F[_]: Sync]( def makeTask[F[_]: Sync](
id: Ident, id: Ident,
baseUrl: LenientUri, baseUrl: LenientUri,
user: AccountId, user: AccountInfo,
settings: PeriodicDueItemsSettings settings: PeriodicDueItemsSettings
): F[UserTask[PeriodicDueItemsArgs]] = ): F[UserTask[PeriodicDueItemsArgs]] =
requireNonEmpty(settings.channels).map { ch => requireNonEmpty(settings.channels).map { ch =>

View File

@ -36,7 +36,7 @@ object OrganizationRoutes {
if (full.getOrElse(false)) if (full.getOrElse(false))
for { for {
data <- backend.organization.findAllOrg( data <- backend.organization.findAllOrg(
user.account, user.account.collectiveId,
q.map(_.q), q.map(_.q),
order order
) )
@ -44,14 +44,18 @@ object OrganizationRoutes {
} yield resp } yield resp
else else
for { for {
data <- backend.organization.findAllOrgRefs(user.account, q.map(_.q), order) data <- backend.organization.findAllOrgRefs(
user.account.collectiveId,
q.map(_.q),
order
)
resp <- Ok(ReferenceList(data.map(mkIdName).toList)) resp <- Ok(ReferenceList(data.map(mkIdName).toList))
} yield resp } yield resp
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[Organization] data <- req.as[Organization]
newOrg <- newOrg(data, user.account.collective) newOrg <- newOrg(data, user.account.collectiveId)
added <- backend.organization.addOrg(newOrg) added <- backend.organization.addOrg(newOrg)
resp <- Ok(basicResult(added, "New organization saved.")) resp <- Ok(basicResult(added, "New organization saved."))
} yield resp } yield resp
@ -59,23 +63,22 @@ object OrganizationRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[Organization] data <- req.as[Organization]
upOrg <- changeOrg(data, user.account.collective) upOrg <- changeOrg(data, user.account.collectiveId)
update <- backend.organization.updateOrg(upOrg) update <- backend.organization.updateOrg(upOrg)
resp <- Ok(basicResult(update, "Organization updated.")) resp <- Ok(basicResult(update, "Organization updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
delOrg <- backend.organization.deleteOrg(id, user.account.collective) delOrg <- backend.organization.deleteOrg(id, user.account.collectiveId)
resp <- Ok(basicResult(delOrg, "Organization deleted.")) resp <- Ok(basicResult(delOrg, "Organization deleted."))
} yield resp } yield resp
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
org <- OptionT(backend.organization.findOrg(user.account, id)) org <- OptionT(backend.organization.findOrg(user.account.collectiveId, id))
resp <- OptionT.liftF(Ok(mkOrg(org))) resp <- OptionT.liftF(Ok(mkOrg(org)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
} }
} }
} }

View File

@ -112,7 +112,7 @@ object PeriodicQueryRoutes extends MailAddressCodec with NonEmptyListSupport {
def makeTask[F[_]: Sync]( def makeTask[F[_]: Sync](
id: Ident, id: Ident,
baseUrl: LenientUri, baseUrl: LenientUri,
user: AccountId, user: AccountInfo,
settings: PeriodicQuerySettings settings: PeriodicQuerySettings
): F[UserTask[PeriodicQueryArgs]] = ): F[UserTask[PeriodicQueryArgs]] =
Sync[F] Sync[F]

View File

@ -37,7 +37,7 @@ object PersonRoutes {
if (full.getOrElse(false)) if (full.getOrElse(false))
for { for {
data <- backend.organization.findAllPerson( data <- backend.organization.findAllPerson(
user.account, user.account.collectiveId,
q.map(_.q), q.map(_.q),
order order
) )
@ -46,7 +46,7 @@ object PersonRoutes {
else else
for { for {
data <- backend.organization.findAllPersonRefs( data <- backend.organization.findAllPersonRefs(
user.account, user.account.collectiveId,
q.map(_.q), q.map(_.q),
order order
) )
@ -56,7 +56,7 @@ object PersonRoutes {
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[Person] data <- req.as[Person]
newPer <- newPerson(data, user.account.collective) newPer <- newPerson(data, user.account.collectiveId)
added <- backend.organization.addPerson(newPer) added <- backend.organization.addPerson(newPer)
resp <- Ok(basicResult(added, "New person saved.")) resp <- Ok(basicResult(added, "New person saved."))
} yield resp } yield resp
@ -64,7 +64,7 @@ object PersonRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[Person] data <- req.as[Person]
upPer <- changePerson(data, user.account.collective) upPer <- changePerson(data, user.account.collectiveId)
update <- backend.organization.updatePerson(upPer) update <- backend.organization.updatePerson(upPer)
resp <- Ok(basicResult(update, "Person updated.")) resp <- Ok(basicResult(update, "Person updated."))
} yield resp } yield resp
@ -72,16 +72,15 @@ object PersonRoutes {
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
_ <- logger.debug(s"Deleting person ${id.id}") _ <- logger.debug(s"Deleting person ${id.id}")
delOrg <- backend.organization.deletePerson(id, user.account.collective) delOrg <- backend.organization.deletePerson(id, user.account.collectiveId)
resp <- Ok(basicResult(delOrg, "Person deleted.")) resp <- Ok(basicResult(delOrg, "Person deleted."))
} yield resp } yield resp
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
org <- OptionT(backend.organization.findPerson(user.account, id)) org <- OptionT(backend.organization.findPerson(user.account.collectiveId, id))
resp <- OptionT.liftF(Ok(mkPerson(org))) resp <- OptionT.liftF(Ok(mkPerson(org)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
} }
} }
} }

View File

@ -35,7 +35,7 @@ object ScanMailboxRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
ut.getScanMailbox(UserTaskScope(user.account)) ut.getScanMailbox(UserTaskScope(user.account))
.evalMap(task => taskToSettings(user.account, backend, task)) .evalMap(task => taskToSettings(user.account.userId, backend, task))
.compile .compile
.toVector .toVector
.map(v => ScanMailboxSettingsList(v.toList)) .map(v => ScanMailboxSettingsList(v.toList))
@ -44,7 +44,7 @@ object ScanMailboxRoutes {
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
task <- ut.findScanMailbox(id, UserTaskScope(user.account)) task <- ut.findScanMailbox(id, UserTaskScope(user.account))
res <- OptionT.liftF(taskToSettings(user.account, backend, task)) res <- OptionT.liftF(taskToSettings(user.account.userId, backend, task))
resp <- OptionT.liftF(Ok(res)) resp <- OptionT.liftF(Ok(res))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
@ -102,7 +102,7 @@ object ScanMailboxRoutes {
def makeTask[F[_]: Sync]( def makeTask[F[_]: Sync](
id: Ident, id: Ident,
user: AccountId, user: AccountInfo,
settings: ScanMailboxSettings settings: ScanMailboxSettings
): F[UserTask[ScanMailboxArgs]] = ): F[UserTask[ScanMailboxArgs]] =
Sync[F].pure( Sync[F].pure(
@ -133,14 +133,14 @@ object ScanMailboxRoutes {
) )
def taskToSettings[F[_]: Sync]( def taskToSettings[F[_]: Sync](
account: AccountId, userId: Ident,
backend: BackendApp[F], backend: BackendApp[F],
task: UserTask[ScanMailboxArgs] task: UserTask[ScanMailboxArgs]
): F[ScanMailboxSettings] = ): F[ScanMailboxSettings] =
for { for {
conn <- conn <-
backend.mail backend.mail
.getImapSettings(account, None) .getImapSettings(userId, None)
.map( .map(
_.find(_.name == task.args.imapConnection) _.find(_.name == task.args.imapConnection)
.map(_.name) .map(_.name)

View File

@ -30,19 +30,19 @@ object SentMailRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root / "item" / Ident(id) => case GET -> Root / "item" / Ident(id) =>
for { for {
all <- backend.mail.getSentMailsForItem(user.account, id) all <- backend.mail.getSentMailsForItem(user.account.collectiveId, id)
resp <- Ok(SentMails(all.map(convert).toList)) resp <- Ok(SentMails(all.map(convert).toList))
} yield resp } yield resp
case GET -> Root / "mail" / Ident(mailId) => case GET -> Root / "mail" / Ident(mailId) =>
(for { (for {
mail <- backend.mail.getSentMail(user.account, mailId) mail <- backend.mail.getSentMail(user.account.collectiveId, mailId)
resp <- OptionT.liftF(Ok(convert(mail))) resp <- OptionT.liftF(Ok(convert(mail)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
case DELETE -> Root / "mail" / Ident(mailId) => case DELETE -> Root / "mail" / Ident(mailId) =>
for { for {
n <- backend.mail.deleteSentMail(user.account, mailId) n <- backend.mail.deleteSentMail(user.account.collectiveId, mailId)
resp <- Ok(BasicResult(n > 0, s"Mails deleted: $n")) resp <- Ok(BasicResult(n > 0, s"Mails deleted: $n"))
} yield resp } yield resp
} }

View File

@ -35,9 +35,9 @@ object ShareRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root :? QP.Query(q) :? QP.OwningFlag(owning) => case GET -> Root :? QP.Query(q) :? QP.OwningFlag(owning) =>
val login = if (owning) Some(user.account.user) else None val login = if (owning) Some(user.account.login) else None
for { for {
all <- backend.share.findAll(user.account.collective, login, q) all <- backend.share.findAll(user.account.collectiveId, login, q)
now <- Timestamp.current[F] now <- Timestamp.current[F]
res <- Ok(ShareList(all.map(mkShareDetail(now)))) res <- Ok(ShareList(all.map(mkShareDetail(now))))
} yield res } yield res
@ -52,7 +52,7 @@ object ShareRoutes {
case GET -> Root / Ident(id) => case GET -> Root / Ident(id) =>
(for { (for {
share <- backend.share.findOne(id, user.account.collective) share <- backend.share.findOne(id, user.account.collectiveId)
now <- OptionT.liftF(Timestamp.current[F]) now <- OptionT.liftF(Timestamp.current[F])
resp <- OptionT.liftF(Ok(mkShareDetail(now)(share))) resp <- OptionT.liftF(Ok(mkShareDetail(now)(share)))
} yield resp).getOrElseF(NotFound()) } yield resp).getOrElseF(NotFound())
@ -67,7 +67,7 @@ object ShareRoutes {
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
del <- backend.share.delete(id, user.account.collective) del <- backend.share.delete(id, user.account.collectiveId)
resp <- Ok(BasicResult(del, if (del) "Share deleted." else "Deleting failed.")) resp <- Ok(BasicResult(del, if (del) "Share deleted." else "Deleting failed."))
} yield resp } yield resp
@ -75,7 +75,10 @@ object ShareRoutes {
for { for {
in <- req.as[SimpleShareMail] in <- req.as[SimpleShareMail]
mail = convertIn(in) mail = convertIn(in)
res <- mail.traverse(m => backend.share.sendMail(user.account, name, m)) res <- mail.traverse(m =>
backend.share
.sendMail(user.account.collectiveId, user.account.userId, name, m)
)
resp <- res.fold( resp <- res.fold(
err => Ok(BasicResult(false, s"Invalid mail data: $err")), err => Ok(BasicResult(false, s"Invalid mail data: $err")),
res => Ok(convertOut(res)) res => Ok(convertOut(res))
@ -111,7 +114,7 @@ object ShareRoutes {
def mkNewShare(data: ShareData, user: AuthToken): OShare.NewShare = def mkNewShare(data: ShareData, user: AuthToken): OShare.NewShare =
OShare.NewShare( OShare.NewShare(
user.account, user.account.asAccountId,
data.name, data.name,
data.query, data.query,
data.enabled, data.enabled,
@ -159,7 +162,7 @@ object ShareRoutes {
ShareDetail( ShareDetail(
r.share.id, r.share.id,
r.share.query, r.share.query,
IdName(r.user.uid, r.user.login.id), IdName(r.account.userId, r.account.login.id),
r.share.name, r.share.name,
r.share.enabled, r.share.enabled,
r.share.publishAt, r.share.publishAt,

View File

@ -30,14 +30,14 @@ object SourceRoutes {
HttpRoutes.of { HttpRoutes.of {
case GET -> Root => case GET -> Root =>
for { for {
all <- backend.source.findAll(user.account) all <- backend.source.findAll(user.account.collectiveId)
res <- Ok(SourceList(all.map(mkSource).toList)) res <- Ok(SourceList(all.map(mkSource).toList))
} yield res } yield res
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[SourceTagIn] data <- req.as[SourceTagIn]
src <- newSource(data.source, user.account.collective) src <- newSource(data.source, user.account.collectiveId)
added <- backend.source.add(src, data.tags) added <- backend.source.add(src, data.tags)
resp <- Ok(basicResult(added, "Source added.")) resp <- Ok(basicResult(added, "Source added."))
} yield resp } yield resp
@ -45,14 +45,14 @@ object SourceRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[SourceTagIn] data <- req.as[SourceTagIn]
src = changeSource(data.source, user.account.collective) src = changeSource(data.source, user.account.collectiveId)
updated <- backend.source.update(src, data.tags) updated <- backend.source.update(src, data.tags)
resp <- Ok(basicResult(updated, "Source updated.")) resp <- Ok(basicResult(updated, "Source updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
del <- backend.source.delete(id, user.account.collective) del <- backend.source.delete(id, user.account.collectiveId)
resp <- Ok(basicResult(del, "Source deleted.")) resp <- Ok(basicResult(del, "Source deleted."))
} yield resp } yield resp
} }

View File

@ -32,7 +32,7 @@ object TagRoutes {
case GET -> Root :? QueryParam.QueryOpt(q) :? QueryParam.TagSort(sort) => case GET -> Root :? QueryParam.QueryOpt(q) :? QueryParam.TagSort(sort) =>
for { for {
all <- backend.tag.findAll( all <- backend.tag.findAll(
user.account, user.account.collectiveId,
q.map(_.q), q.map(_.q),
sort.getOrElse(TagOrder.NameAsc) sort.getOrElse(TagOrder.NameAsc)
) )
@ -42,7 +42,7 @@ object TagRoutes {
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[Tag] data <- req.as[Tag]
tag <- newTag(data, user.account.collective) tag <- newTag(data, user.account.collectiveId)
res <- backend.tag.add(tag) res <- backend.tag.add(tag)
resp <- Ok(basicResult(res, "Tag successfully created.")) resp <- Ok(basicResult(res, "Tag successfully created."))
} yield resp } yield resp
@ -50,14 +50,14 @@ object TagRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[Tag] data <- req.as[Tag]
tag = changeTag(data, user.account.collective) tag = changeTag(data, user.account.collectiveId)
res <- backend.tag.update(tag) res <- backend.tag.update(tag)
resp <- Ok(basicResult(res, "Tag successfully updated.")) resp <- Ok(basicResult(res, "Tag successfully updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
del <- backend.tag.delete(id, user.account.collective) del <- backend.tag.delete(id, user.account.collectiveId)
resp <- Ok(basicResult(del, "Tag successfully deleted.")) resp <- Ok(basicResult(del, "Tag successfully deleted."))
} yield resp } yield resp
} }

View File

@ -33,7 +33,13 @@ object UploadRoutes {
val dsl = new Http4sDsl[F] with ResponseGenerator[F] {} val dsl = new Http4sDsl[F] with ResponseGenerator[F] {}
import dsl._ import dsl._
val submitting = submitFiles[F](backend, cfg, Right(user.account)) _ val submitting =
submitFiles[F](
backend,
cfg,
Right(user.account.collectiveId),
user.account.userId.some
) _
HttpRoutes.of { HttpRoutes.of {
case req @ POST -> Root / "item" => case req @ POST -> Root / "item" =>
@ -53,7 +59,7 @@ object UploadRoutes {
(for { (for {
_ <- OptionT(backend.collective.findEnabledSource(srcId)) _ <- OptionT(backend.collective.findEnabledSource(srcId))
res <- OptionT.liftF( res <- OptionT.liftF(
submitFiles(backend, cfg, Left(srcId))(req, None, Priority.Low, dsl) submitFiles(backend, cfg, Left(srcId), None)(req, None, Priority.Low, dsl)
) )
} yield res).getOrElseF(NotFound()) } yield res).getOrElseF(NotFound())
@ -61,7 +67,12 @@ object UploadRoutes {
(for { (for {
_ <- OptionT(backend.collective.findEnabledSource(srcId)) _ <- OptionT(backend.collective.findEnabledSource(srcId))
res <- OptionT.liftF( res <- OptionT.liftF(
submitFiles(backend, cfg, Left(srcId))(req, Some(itemId), Priority.Low, dsl) submitFiles(backend, cfg, Left(srcId), None)(
req,
Some(itemId),
Priority.Low,
dsl
)
) )
} yield res).getOrElseF(NotFound()) } yield res).getOrElseF(NotFound())
} }
@ -70,7 +81,8 @@ object UploadRoutes {
private def submitFiles[F[_]: Async]( private def submitFiles[F[_]: Async](
backend: BackendApp[F], backend: BackendApp[F],
cfg: Config, cfg: Config,
accOrSrc: Either[Ident, AccountId] accOrSrc: Either[Ident, CollectiveId],
userId: Option[Ident]
)( )(
req: Request[F], req: Request[F],
itemId: Option[Ident], itemId: Option[Ident],
@ -96,7 +108,7 @@ object UploadRoutes {
prio, prio,
cfg.backend.files.validMimeTypes cfg.backend.files.validMimeTypes
) )
result <- backend.upload.submitEither(updata, accOrSrc, itemId) result <- backend.upload.submitEither(updata, accOrSrc, userId, itemId)
res <- Ok(basicResult(result)) res <- Ok(basicResult(result))
} yield res } yield res
} }

View File

@ -8,14 +8,13 @@ package docspell.restserver.routes
import cats.effect._ import cats.effect._
import cats.implicits._ import cats.implicits._
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.backend.ops.OCollective import docspell.backend.ops.OCollective
import docspell.common._ import docspell.common._
import docspell.restapi.model._ import docspell.restapi.model._
import docspell.restserver.conv.Conversions._ import docspell.restserver.conv.Conversions._
import docspell.store.UpdateResult
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityDecoder._
import org.http4s.circe.CirceEntityEncoder._ import org.http4s.circe.CirceEntityEncoder._
@ -32,7 +31,8 @@ object UserRoutes {
for { for {
data <- req.as[PasswordChange] data <- req.as[PasswordChange]
res <- backend.collective.changePassword( res <- backend.collective.changePassword(
user.account, user.account.collectiveId,
user.account.userId,
data.currentPassword, data.currentPassword,
data.newPassword data.newPassword
) )
@ -41,14 +41,14 @@ object UserRoutes {
case GET -> Root => case GET -> Root =>
for { for {
all <- backend.collective.listUser(user.account.collective) all <- backend.collective.listUser(user.account.collectiveId)
res <- Ok(UserList(all.map(mkUser).toList)) res <- Ok(UserList(all.map(mkUser).toList))
} yield res } yield res
case req @ POST -> Root => case req @ POST -> Root =>
for { for {
data <- req.as[User] data <- req.as[User]
nuser <- newUser(data, user.account.collective) nuser <- newUser(data, user.account.collectiveId)
added <- backend.collective.add(nuser) added <- backend.collective.add(nuser)
resp <- Ok(basicResult(added, "User created.")) resp <- Ok(basicResult(added, "User created."))
} yield resp } yield resp
@ -56,25 +56,35 @@ object UserRoutes {
case req @ PUT -> Root => case req @ PUT -> Root =>
for { for {
data <- req.as[User] data <- req.as[User]
nuser = changeUser(data, user.account.collective) nuser = changeUser(data, user.account.collectiveId)
update <- backend.collective.update(nuser) update <- backend.collective.update(nuser)
resp <- Ok(basicResult(update, "User updated.")) resp <- Ok(basicResult(update, "User updated."))
} yield resp } yield resp
case DELETE -> Root / Ident(id) => case DELETE -> Root / Ident(id) =>
for { for {
ar <- backend.collective.deleteUser(id, user.account.collective) users <- backend.collective.listUser(user.account.collectiveId)
ar <-
if (users.exists(_.uid == id)) backend.collective.deleteUser(id)
else UpdateResult.notFound.pure[F]
resp <- Ok(basicResult(ar, "User deleted.")) resp <- Ok(basicResult(ar, "User deleted."))
} yield resp } yield resp
case GET -> Root / Ident(username) / "deleteData" => case GET -> Root / Ident(username) / "deleteData" =>
for { for {
data <- backend.collective.getDeleteUserData( users <- backend.collective.listUser(user.account.collectiveId)
AccountId(user.account.collective, username) userToDelete = users.find(u => u.login == username || u.uid == username)
) resp <- userToDelete match {
resp <- Ok( case Some(user) =>
DeleteUserData(data.ownedFolders, data.sentMails, data.shares) backend.collective
.getDeleteUserData(user.cid, user.uid)
.flatMap(data =>
Ok(DeleteUserData(data.ownedFolders, data.sentMails, data.shares))
) )
case None =>
NotFound(BasicResult(false, s"User '${username.id}' not found"))
}
} yield resp } yield resp
} }
} }

View File

@ -10,10 +10,9 @@ import cats.effect.Async
import cats.implicits._ import cats.implicits._
import fs2.concurrent.Topic import fs2.concurrent.Topic
import fs2.{Pipe, Stream} import fs2.{Pipe, Stream}
import docspell.backend.BackendApp import docspell.backend.BackendApp
import docspell.backend.auth.AuthToken import docspell.backend.auth.AuthToken
import docspell.scheduler.usertask.UserTaskScope
import org.http4s.HttpRoutes import org.http4s.HttpRoutes
import org.http4s.dsl.Http4sDsl import org.http4s.dsl.Http4sDsl
import org.http4s.server.websocket.WebSocketBuilder2 import org.http4s.server.websocket.WebSocketBuilder2
@ -34,7 +33,7 @@ object WebSocketRoutes {
HttpRoutes.of { case GET -> Root => HttpRoutes.of { case GET -> Root =>
val init = val init =
for { for {
jc <- backend.job.getUnfinishedJobCount(user.account.collective) jc <- backend.job.getUnfinishedJobCount(UserTaskScope(user.account))
msg = OutputEvent.JobsWaiting(user.account.collective, jc) msg = OutputEvent.JobsWaiting(user.account.collective, jc)
} yield Text(msg.encode) } yield Text(msg.encode)

View File

@ -16,7 +16,11 @@ import docspell.notification.api._
import docspell.store.queries.QLogin import docspell.store.queries.QLogin
import docspell.store.records._ import docspell.store.records._
import db.migration.data._ import db.migration.data.{
PeriodicDueItemsArgs => PeriodicDueItemsArgsLegacy,
PeriodicQueryArgs => PeriodicQueryArgsLegacy,
_
}
import doobie._ import doobie._
import doobie.implicits._ import doobie.implicits._
import doobie.util.transactor.Strategy import doobie.util.transactor.Strategy
@ -75,8 +79,8 @@ trait MigrationTasks {
ref.flatMap(channelRef => ref.flatMap(channelRef =>
RPeriodicTask.updateTask( RPeriodicTask.updateTask(
old.id, old.id,
PeriodicQueryArgs.taskName, PeriodicQueryArgsLegacy.taskName,
PeriodicQueryArgs( PeriodicQueryArgsLegacy(
oldArgs.account, oldArgs.account,
NonEmptyList.of(channelRef), NonEmptyList.of(channelRef),
oldArgs.query, oldArgs.query,
@ -105,8 +109,8 @@ trait MigrationTasks {
ref.flatMap(channelRef => ref.flatMap(channelRef =>
RPeriodicTask.updateTask( RPeriodicTask.updateTask(
old.id, old.id,
PeriodicDueItemsArgs.taskName, PeriodicDueItemsArgsLegacy.taskName,
PeriodicDueItemsArgs( PeriodicDueItemsArgsLegacy(
oldArgs.account, oldArgs.account,
NonEmptyList.of(channelRef), NonEmptyList.of(channelRef),
oldArgs.remindDays, oldArgs.remindDays,
@ -147,7 +151,7 @@ trait MigrationTasks {
RPeriodicTask RPeriodicTask
.updateTask( .updateTask(
old.id, old.id,
PeriodicDueItemsArgs.taskName, PeriodicDueItemsArgsLegacy.taskName,
a.asJson.noSpaces a.asJson.noSpaces
) )
) )
@ -163,7 +167,7 @@ trait MigrationTasks {
private def convertArgs( private def convertArgs(
old: NotifyDueItemsArgs old: NotifyDueItemsArgs
): OptionT[ConnectionIO, PeriodicDueItemsArgs] = { ): OptionT[ConnectionIO, PeriodicDueItemsArgsLegacy] = {
val recs = old.recipients val recs = old.recipients
.map(MailAddress.parse) .map(MailAddress.parse)
.flatMap { .flatMap {
@ -188,7 +192,7 @@ trait MigrationTasks {
now now
) )
_ <- OptionT.liftF(RNotificationChannelMail.insert(ch)) _ <- OptionT.liftF(RNotificationChannelMail.insert(ch))
args = PeriodicDueItemsArgs( args = PeriodicDueItemsArgsLegacy(
old.account, old.account,
NonEmptyList.of(ChannelRef(ch.id, ChannelType.Mail, chName)), NonEmptyList.of(ChannelRef(ch.id, ChannelType.Mail, chName)),
old.remindDays, old.remindDays,

View File

@ -0,0 +1,43 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package db.migration.data
import cats.data.NonEmptyList
import docspell.common._
import docspell.notification.api.ChannelRef
import io.circe.generic.semiauto
import io.circe.{Decoder, Encoder}
/** Arguments to the notification task.
*
* This tasks queries items with a due date and informs the user via mail.
*
* If the structure changes, there must be some database migration to update or remove
* the json data of the corresponding task.
*
* @deprecated
* replaced with a version using `AccountInfo`
*/
final case class PeriodicDueItemsArgs(
account: AccountId,
channels: NonEmptyList[ChannelRef],
remindDays: Int,
daysBack: Option[Int],
tagsInclude: List[Ident],
tagsExclude: List[Ident],
baseUrl: Option[LenientUri]
)
object PeriodicDueItemsArgs {
val taskName = Ident.unsafe("periodic-due-items-notify2")
implicit val jsonDecoder: Decoder[PeriodicDueItemsArgs] =
semiauto.deriveDecoder
implicit val jsonEncoder: Encoder[PeriodicDueItemsArgs] =
semiauto.deriveEncoder
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package db.migration.data
import cats.data.NonEmptyList
import docspell.common._
import docspell.notification.api.ChannelRef
import io.circe.generic.semiauto
import io.circe.{Decoder, Encoder}
/** @deprecated replaced with a version using `AccountInfo` */
final case class PeriodicQueryArgs(
account: AccountId,
channels: NonEmptyList[ChannelRef],
query: Option[ItemQueryString],
bookmark: Option[String],
baseUrl: Option[LenientUri],
contentStart: Option[String]
)
object PeriodicQueryArgs {
val taskName = Ident.unsafe("periodic-query-notify2")
implicit val jsonDecoder: Decoder[PeriodicQueryArgs] =
semiauto.deriveDecoder
implicit def jsonEncoder: Encoder[PeriodicQueryArgs] =
semiauto.deriveEncoder
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package db.migration.data
import docspell.common._
import docspell.common.syntax.all._
import io.circe._
import io.circe.generic.semiauto._
/** Arguments to the poll-mailbox task.
*
* This tasks queries user mailboxes and pushes found mails into docspell for processing.
*
* If the structure changes, there must be some database migration to update or remove
* the json data of the corresponding task.
*
* @deprecated
* replaced with a version using `AccountInfo`
*/
case class ScanMailboxArgs(
// the docspell user account
account: AccountId,
// the configured imap connection
imapConnection: Ident,
// scan folders recursively
scanRecursively: Option[Boolean],
// what folders to search
folders: List[String],
// only select mails received since then
receivedSince: Option[Duration],
// move submitted mails to another folder
targetFolder: Option[String],
// delete the after submitting (only if targetFolder is None)
deleteMail: Boolean,
// set the direction when submitting
direction: Option[Direction],
// set a folder for items
itemFolder: Option[Ident],
// set a filter for files when importing archives
fileFilter: Option[Glob],
// set a list of tags to apply to new item
tags: Option[List[String]],
// a glob filter for the mail subject
subjectFilter: Option[Glob],
// the language for extraction and analysis
language: Option[Language],
// apply additional filter to all mails or only imported
postHandleAll: Option[Boolean],
// Exclude the mail body when importing
attachmentsOnly: Option[Boolean]
)
object ScanMailboxArgs {
val taskName = Ident.unsafe("scan-mailbox")
implicit val jsonEncoder: Encoder[ScanMailboxArgs] =
deriveEncoder[ScanMailboxArgs]
implicit val jsonDecoder: Decoder[ScanMailboxArgs] =
deriveDecoder[ScanMailboxArgs]
def parse(str: String): Either[Throwable, ScanMailboxArgs] =
str.parseJsonAs[ScanMailboxArgs]
}

View File

@ -30,12 +30,12 @@ object RFolder {
def newFolder[F[_]: Sync]( def newFolder[F[_]: Sync](
name: String, name: String,
collective: CollectiveId, collective: CollectiveId,
user: Ident ownerUserId: Ident
): F[RFolder] = ): F[RFolder] =
for { for {
nId <- Ident.randomId[F] nId <- Ident.randomId[F]
now <- Timestamp.current[F] now <- Timestamp.current[F]
} yield RFolder(nId, name, collective, user, now) } yield RFolder(nId, name, collective, ownerUserId, now)
final case class Table(alias: Option[String]) extends TableDef { final case class Table(alias: Option[String]) extends TableDef {
val tableName = "folder" val tableName = "folder"