mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Manage notification channels separately and migrate
It's more convenient to manage notification channels separately, as it is done with email settings. Notification hook and other forms are adopted to only select channels. Hooks can now use more than one channel.
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
|
||||
package docspell.restserver.routes
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
@ -14,10 +15,10 @@ import docspell.backend.auth.AuthToken
|
||||
import docspell.common._
|
||||
import docspell.joexapi.model.BasicResult
|
||||
import docspell.jsonminiq.JsonMiniQuery
|
||||
import docspell.notification.api.EventType
|
||||
import docspell.notification.api.{ChannelRef, EventType}
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.Config
|
||||
import docspell.restserver.conv.Conversions
|
||||
import docspell.restserver.conv.{Conversions, NonEmptyListSupport}
|
||||
import docspell.restserver.http4s.ClientRequestInfo
|
||||
|
||||
import org.http4s._
|
||||
@ -26,7 +27,7 @@ import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
import org.http4s.server.Router
|
||||
|
||||
object NotificationRoutes {
|
||||
object NotificationRoutes extends NonEmptyListSupport {
|
||||
|
||||
def apply[F[_]: Async](
|
||||
cfg: Config,
|
||||
@ -126,17 +127,11 @@ object NotificationRoutes {
|
||||
case req @ POST -> Root / "sendTestEvent" =>
|
||||
for {
|
||||
input <- req.as[NotificationHook]
|
||||
ch <- Sync[F]
|
||||
.pure(
|
||||
input.channel.left
|
||||
.map(_ => new Exception(s"ChannelRefs not allowed for testing"))
|
||||
.flatMap(NotificationChannel.convert)
|
||||
)
|
||||
.rethrow
|
||||
ch <- requireNonEmpty(input.channels)
|
||||
baseUrl = ClientRequestInfo.getBaseUrl(cfg, req)
|
||||
res <- backend.notification.sendSampleEvent(
|
||||
input.events.headOption.getOrElse(EventType.all.head),
|
||||
ch,
|
||||
ch.map(r => ChannelRef(r.id, r.channelType, r.name)),
|
||||
user.account,
|
||||
baseUrl.some
|
||||
)
|
||||
@ -179,33 +174,26 @@ object NotificationRoutes {
|
||||
NotificationHook(
|
||||
h.id,
|
||||
h.enabled,
|
||||
h.channel.map(NotificationChannel.convert),
|
||||
h.channels.map(c => NotificationChannelRef(c.id, c.channelType, c.name)).toList,
|
||||
h.allEvents,
|
||||
h.eventFilter,
|
||||
h.events
|
||||
)
|
||||
|
||||
def convertHook(h: NotificationHook): Either[Throwable, ONotification.Hook] =
|
||||
h.channel match {
|
||||
case Left(cref) =>
|
||||
Right(
|
||||
ONotification.Hook(
|
||||
h.id,
|
||||
h.enabled,
|
||||
Left(cref),
|
||||
h.allEvents,
|
||||
h.eventFilter,
|
||||
h.events
|
||||
)
|
||||
NonEmptyList
|
||||
.fromList(h.channels)
|
||||
.toRight(new IllegalArgumentException(s"Empty channels not allowed!"))
|
||||
.map(_ =>
|
||||
ONotification.Hook(
|
||||
h.id,
|
||||
h.enabled,
|
||||
h.channels.map(c => ChannelRef(c.id, c.channelType, c.name)),
|
||||
h.allEvents,
|
||||
h.eventFilter,
|
||||
h.events
|
||||
)
|
||||
case Right(channel) =>
|
||||
NotificationChannel
|
||||
.convert(channel)
|
||||
.map(ch =>
|
||||
ONotification
|
||||
.Hook(h.id, h.enabled, Right(ch), h.allEvents, h.eventFilter, h.events)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,10 @@ import docspell.backend.BackendApp
|
||||
import docspell.backend.MailAddressCodec
|
||||
import docspell.backend.auth.AuthToken
|
||||
import docspell.common._
|
||||
import docspell.notification.api.PeriodicDueItemsArgs
|
||||
import docspell.notification.api.{ChannelRef, PeriodicDueItemsArgs}
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.Config
|
||||
import docspell.restserver.conv.Conversions
|
||||
import docspell.restserver.conv.{Conversions, NonEmptyListSupport}
|
||||
import docspell.restserver.http4s.ClientRequestInfo
|
||||
import docspell.store.usertask._
|
||||
|
||||
@ -26,7 +26,7 @@ import org.http4s.circe.CirceEntityDecoder._
|
||||
import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
|
||||
object NotifyDueItemsRoutes extends MailAddressCodec {
|
||||
object NotifyDueItemsRoutes extends MailAddressCodec with NonEmptyListSupport {
|
||||
|
||||
def apply[F[_]: Async](
|
||||
cfg: Config,
|
||||
@ -113,7 +113,7 @@ object NotifyDueItemsRoutes extends MailAddressCodec {
|
||||
user: AccountId,
|
||||
settings: PeriodicDueItemsSettings
|
||||
): F[UserTask[PeriodicDueItemsArgs]] =
|
||||
Sync[F].pure(NotificationChannel.convert(settings.channel)).rethrow.map { channel =>
|
||||
requireNonEmpty(settings.channels).map { ch =>
|
||||
UserTask(
|
||||
id,
|
||||
PeriodicDueItemsArgs.taskName,
|
||||
@ -122,7 +122,7 @@ object NotifyDueItemsRoutes extends MailAddressCodec {
|
||||
settings.summary,
|
||||
PeriodicDueItemsArgs(
|
||||
user,
|
||||
Right(channel),
|
||||
ch.map(c => ChannelRef(c.id, c.channelType, c.name)),
|
||||
settings.remindDays,
|
||||
if (settings.capOverdue) Some(settings.remindDays)
|
||||
else None,
|
||||
@ -140,20 +140,13 @@ object NotifyDueItemsRoutes extends MailAddressCodec {
|
||||
for {
|
||||
tinc <- backend.tag.loadAll(task.args.tagsInclude)
|
||||
texc <- backend.tag.loadAll(task.args.tagsExclude)
|
||||
|
||||
ch <- task.args.channel match {
|
||||
case Right(c) => NotificationChannel.convert(c).pure[F]
|
||||
case Left(ref) =>
|
||||
Sync[F].raiseError(
|
||||
new IllegalStateException(s"ChannelRefs are not supported: $ref")
|
||||
)
|
||||
}
|
||||
|
||||
} yield PeriodicDueItemsSettings(
|
||||
task.id,
|
||||
task.enabled,
|
||||
task.summary,
|
||||
ch,
|
||||
task.args.channels
|
||||
.map(c => NotificationChannelRef(c.id, c.channelType, c.name))
|
||||
.toList,
|
||||
task.timer,
|
||||
task.args.remindDays,
|
||||
task.args.daysBack.isDefined,
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
package docspell.restserver.routes
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.data.{NonEmptyList, OptionT}
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
@ -14,11 +14,11 @@ import docspell.backend.BackendApp
|
||||
import docspell.backend.MailAddressCodec
|
||||
import docspell.backend.auth.AuthToken
|
||||
import docspell.common._
|
||||
import docspell.notification.api.PeriodicQueryArgs
|
||||
import docspell.notification.api.{ChannelRef, PeriodicQueryArgs}
|
||||
import docspell.query.ItemQueryParser
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.Config
|
||||
import docspell.restserver.conv.Conversions
|
||||
import docspell.restserver.conv.{Conversions, NonEmptyListSupport}
|
||||
import docspell.restserver.http4s.ClientRequestInfo
|
||||
import docspell.store.usertask._
|
||||
|
||||
@ -27,7 +27,7 @@ import org.http4s.circe.CirceEntityDecoder._
|
||||
import org.http4s.circe.CirceEntityEncoder._
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
|
||||
object PeriodicQueryRoutes extends MailAddressCodec {
|
||||
object PeriodicQueryRoutes extends MailAddressCodec with NonEmptyListSupport {
|
||||
|
||||
def apply[F[_]: Async](
|
||||
cfg: Config,
|
||||
@ -116,7 +116,9 @@ object PeriodicQueryRoutes extends MailAddressCodec {
|
||||
): F[UserTask[PeriodicQueryArgs]] =
|
||||
Sync[F]
|
||||
.pure(for {
|
||||
ch <- NotificationChannel.convert(settings.channel)
|
||||
ch <- NonEmptyList
|
||||
.fromList(settings.channels)
|
||||
.toRight(new Exception(s"No channels found for: ${settings.channels}"))
|
||||
qstr <- settings.query match {
|
||||
case Some(q) =>
|
||||
ItemQueryParser
|
||||
@ -132,7 +134,7 @@ object PeriodicQueryRoutes extends MailAddressCodec {
|
||||
else Left(new IllegalArgumentException("No query or bookmark provided"))
|
||||
} yield (ch, qstr.map(ItemQueryString.apply)))
|
||||
.rethrow
|
||||
.map { case (channel, qstr) =>
|
||||
.map { case (channels, qstr) =>
|
||||
UserTask(
|
||||
id,
|
||||
PeriodicQueryArgs.taskName,
|
||||
@ -141,7 +143,7 @@ object PeriodicQueryRoutes extends MailAddressCodec {
|
||||
settings.summary,
|
||||
PeriodicQueryArgs(
|
||||
user,
|
||||
Right(channel),
|
||||
channels.map(r => ChannelRef(r.id, r.channelType, r.name)),
|
||||
qstr,
|
||||
settings.bookmark,
|
||||
Some(baseUrl / "app" / "item"),
|
||||
@ -153,22 +155,18 @@ object PeriodicQueryRoutes extends MailAddressCodec {
|
||||
def taskToSettings[F[_]: Sync](
|
||||
task: UserTask[PeriodicQueryArgs]
|
||||
): F[PeriodicQuerySettings] =
|
||||
for {
|
||||
ch <- task.args.channel match {
|
||||
case Right(c) => NotificationChannel.convert(c).pure[F]
|
||||
case Left(ref) =>
|
||||
Sync[F].raiseError(
|
||||
new IllegalStateException(s"ChannelRefs are not supported: $ref")
|
||||
)
|
||||
}
|
||||
} yield PeriodicQuerySettings(
|
||||
task.id,
|
||||
task.summary,
|
||||
task.enabled,
|
||||
ch,
|
||||
task.args.query.map(_.query).map(ItemQueryParser.parseUnsafe),
|
||||
task.args.bookmark,
|
||||
task.args.contentStart,
|
||||
task.timer
|
||||
Sync[F].pure(
|
||||
PeriodicQuerySettings(
|
||||
task.id,
|
||||
task.enabled,
|
||||
task.summary,
|
||||
task.args.channels
|
||||
.map(c => NotificationChannelRef(c.id, c.channelType, c.name))
|
||||
.toList,
|
||||
task.timer,
|
||||
task.args.query.map(_.query).map(ItemQueryParser.parseUnsafe),
|
||||
task.args.bookmark,
|
||||
task.args.contentStart
|
||||
)
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user