diff --git a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala index 8466ffcc..efa54b71 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala @@ -254,11 +254,18 @@ object ONotification { private[ops] def makeChannel(r: RNotificationChannel): Channel = r.fold( mail => - Channel.Mail(mail.id, mail.connection, Nel.fromListUnsafe(mail.recipients)), - gotify => Channel.Gotify(r.id, gotify.url, gotify.appKey, gotify.priority), + Channel.Mail( + mail.id, + mail.name, + mail.connection, + Nel.fromListUnsafe(mail.recipients) + ), + gotify => + Channel.Gotify(r.id, gotify.name, gotify.url, gotify.appKey, gotify.priority), matrix => - Channel.Matrix(r.id, matrix.homeServer, matrix.roomId, matrix.accessToken), - http => Channel.Http(r.id, http.url) + Channel + .Matrix(r.id, matrix.name, matrix.homeServer, matrix.roomId, matrix.accessToken), + http => Channel.Http(r.id, http.name, http.url) ) private[ops] def makeRecord[F[_]: Sync]( @@ -278,7 +285,7 @@ object ONotification { time <- OptionT.liftF(Timestamp.current[F]) r <- channel match { - case Channel.Mail(_, conn, recipients) => + case Channel.Mail(_, name, conn, recipients) => for { _ <- OptionT.liftF( logger.debug( @@ -291,20 +298,30 @@ object ONotification { rec = RNotificationChannelMail( id, userId, + name, mailConn.id, recipients.toList, time ).vary } yield rec - case Channel.Gotify(_, url, appKey, prio) => + case Channel.Gotify(_, name, url, appKey, prio) => OptionT.pure[F]( - RNotificationChannelGotify(id, userId, url, appKey, prio, time).vary + RNotificationChannelGotify( + id, + userId, + name, + url, + appKey, + prio, + time + ).vary ) - case Channel.Matrix(_, homeServer, roomId, accessToken) => + case Channel.Matrix(_, name, homeServer, roomId, accessToken) => OptionT.pure[F]( RNotificationChannelMatrix( id, userId, + name, homeServer, roomId, accessToken, @@ -312,8 +329,10 @@ object ONotification { time ).vary ) - case Channel.Http(_, url) => - OptionT.pure[F](RNotificationChannelHttp(id, userId, url, time).vary) + case Channel.Http(_, name, url) => + OptionT.pure[F]( + RNotificationChannelHttp(id, userId, name, url, time).vary + ) } } yield r } diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala b/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala index 8fe34934..1735b610 100644 --- a/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala +++ b/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala @@ -33,6 +33,7 @@ object Channel { final case class Mail( id: Ident, + name: Option[String], connection: Ident, recipients: Nel[MailAddress] ) extends Channel { @@ -55,6 +56,7 @@ object Channel { final case class Gotify( id: Ident, + name: Option[String], url: LenientUri, appKey: Password, priority: Option[Int] @@ -77,6 +79,7 @@ object Channel { final case class Matrix( id: Ident, + name: Option[String], homeServer: LenientUri, roomId: String, accessToken: Password @@ -95,7 +98,7 @@ object Channel { implicit val jsonEncoder: Encoder[Matrix] = deriveConfiguredEncoder } - final case class Http(id: Ident, url: LenientUri) extends Channel { + final case class Http(id: Ident, name: Option[String], url: LenientUri) extends Channel { val channelType = ChannelType.Http def fold[A]( f1: Mail => A, diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index db9cf7ec..4e9a169e 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -5491,6 +5491,8 @@ components: id: type: string format: ident + name: + type: string channelType: type: string format: channeltype @@ -5514,6 +5516,8 @@ components: id: type: string format: ident + name: + type: string channelType: type: string format: channeltype @@ -5539,6 +5543,8 @@ components: id: type: string format: ident + name: + type: string channelType: type: string format: channeltype @@ -5557,6 +5563,8 @@ components: id: type: string format: ident + name: + type: string channelType: type: string format: channeltype diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala index 7c6c1021..aa1040dc 100644 --- a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala +++ b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala @@ -73,15 +73,24 @@ object NotificationChannel { .map(NonEmptyList.fromList) .flatMap(_.toRight("No recipients given!")) .leftMap(new IllegalArgumentException(_)) - .map(rec => Channel.Mail(mail.id, mail.connection, rec)), + .map(rec => Channel.Mail(mail.id, mail.name, mail.connection, rec)), gotify => - Right(Channel.Gotify(gotify.id, gotify.url, gotify.appKey, gotify.priority)), + Right( + Channel + .Gotify(gotify.id, gotify.name, gotify.url, gotify.appKey, gotify.priority) + ), matrix => Right( Channel - .Matrix(matrix.id, matrix.homeServer, matrix.roomId, matrix.accessToken) + .Matrix( + matrix.id, + matrix.name, + matrix.homeServer, + matrix.roomId, + matrix.accessToken + ) ), - http => Right(Channel.Http(http.id, http.url)) + http => Right(Channel.Http(http.id, http.name, http.url)) ) def convert(c: Channel): NotificationChannel = @@ -90,24 +99,35 @@ object NotificationChannel { mail { NotificationMail( m.id, + m.name, ChannelType.Mail, m.connection, m.recipients.toList.map(_.displayString) ) }, g => - gotify(NotificationGotify(g.id, ChannelType.Gotify, g.url, g.appKey, g.priority)), + gotify( + NotificationGotify( + g.id, + g.name, + ChannelType.Gotify, + g.url, + g.appKey, + g.priority + ) + ), m => matrix( NotificationMatrix( m.id, + m.name, ChannelType.Matrix, m.homeServer, m.roomId, m.accessToken ) ), - h => http(NotificationHttp(h.id, ChannelType.Http, h.url)) + h => http(NotificationHttp(h.id, h.name, ChannelType.Http, h.url)) ) implicit val jsonDecoder: Decoder[NotificationChannel] = diff --git a/modules/store/src/main/resources/db/migration/h2/V1.32.0__notification_channel_name.sql b/modules/store/src/main/resources/db/migration/h2/V1.32.0__notification_channel_name.sql new file mode 100644 index 00000000..5a928a58 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/h2/V1.32.0__notification_channel_name.sql @@ -0,0 +1,11 @@ +alter table "notification_channel_mail" +add column "name" varchar(254); + +alter table "notification_channel_gotify" +add column "name" varchar(254); + +alter table "notification_channel_matrix" +add column "name" varchar(254); + +alter table "notification_channel_http" +add column "name" varchar(254); diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.32.0__notification_channel_name.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.32.0__notification_channel_name.sql new file mode 100644 index 00000000..04dae6ae --- /dev/null +++ b/modules/store/src/main/resources/db/migration/mariadb/V1.32.0__notification_channel_name.sql @@ -0,0 +1,11 @@ +alter table `notification_channel_mail` +add column `name` varchar(254); + +alter table `notification_channel_gotify` +add column `name` varchar(254); + +alter table `notification_channel_matrix` +add column `name` varchar(254); + +alter table `notification_channel_http` +add column `name` varchar(254); diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.32.0__notification_channel_name.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.32.0__notification_channel_name.sql new file mode 100644 index 00000000..5a928a58 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/postgresql/V1.32.0__notification_channel_name.sql @@ -0,0 +1,11 @@ +alter table "notification_channel_mail" +add column "name" varchar(254); + +alter table "notification_channel_gotify" +add column "name" varchar(254); + +alter table "notification_channel_matrix" +add column "name" varchar(254); + +alter table "notification_channel_http" +add column "name" varchar(254); diff --git a/modules/store/src/main/scala/db/migration/MigrationTasks.scala b/modules/store/src/main/scala/db/migration/MigrationTasks.scala index 913bacde..47c814cd 100644 --- a/modules/store/src/main/scala/db/migration/MigrationTasks.scala +++ b/modules/store/src/main/scala/db/migration/MigrationTasks.scala @@ -70,7 +70,7 @@ trait MigrationTasks { .map { rec => PeriodicDueItemsArgs( old.account, - Right(Channel.Mail(Ident.unsafe(""), old.smtpConnection, rec)), + Right(Channel.Mail(Ident.unsafe(""), None, old.smtpConnection, rec)), old.remindDays, old.daysBack, old.tagsInclude, diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala index 6b6b5c53..4de2675e 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala @@ -16,7 +16,9 @@ import doobie._ sealed trait RNotificationChannel { - def id: Ident + def id: Ident = fold(_.id, _.id, _.id, _.id) + + def name: Option[String] = fold(_.name, _.name, _.name, _.name) def fold[A]( f1: RNotificationChannelMail => A, @@ -24,7 +26,6 @@ sealed trait RNotificationChannel { f3: RNotificationChannelMatrix => A, f4: RNotificationChannelHttp => A ): A - } object RNotificationChannel { @@ -37,8 +38,6 @@ object RNotificationChannel { f3: RNotificationChannelMatrix => A, f4: RNotificationChannelHttp => A ): A = f1(r) - - val id = r.id } final case class Gotify(r: RNotificationChannelGotify) extends RNotificationChannel { @@ -48,8 +47,6 @@ object RNotificationChannel { f3: RNotificationChannelMatrix => A, f4: RNotificationChannelHttp => A ): A = f2(r) - - val id = r.id } final case class Matrix(r: RNotificationChannelMatrix) extends RNotificationChannel { @@ -59,8 +56,6 @@ object RNotificationChannel { f3: RNotificationChannelMatrix => A, f4: RNotificationChannelHttp => A ): A = f3(r) - - val id = r.id } final case class Http(r: RNotificationChannelHttp) extends RNotificationChannel { @@ -70,8 +65,6 @@ object RNotificationChannel { f3: RNotificationChannelMatrix => A, f4: RNotificationChannelHttp => A ): A = f4(r) - - val id = r.id } def insert(r: RNotificationChannel): ConnectionIO[Int] = diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala index 4464f5f0..a5c93a61 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala @@ -18,6 +18,7 @@ import doobie.implicits._ final case class RNotificationChannelGotify( id: Ident, uid: Ident, + name: Option[String], url: LenientUri, appKey: Password, priority: Option[Int], @@ -34,13 +35,14 @@ object RNotificationChannelGotify { val id = Column[Ident]("id", this) val uid = Column[Ident]("uid", this) + val name = Column[String]("name", this) val url = Column[LenientUri]("url", this) val appKey = Column[Password]("app_key", this) val priority = Column[Int]("priority", this) val created = Column[Timestamp]("created", this) val all: NonEmptyList[Column[_]] = - NonEmptyList.of(id, uid, url, appKey, priority, created) + NonEmptyList.of(id, uid, name, url, appKey, priority, created) } val T: Table = Table(None) @@ -54,7 +56,7 @@ object RNotificationChannelGotify { DML.insert( T, T.all, - sql"${r.id},${r.uid},${r.url},${r.appKey},${r.priority},${r.created}" + sql"${r.id},${r.uid},${r.name},${r.url},${r.appKey},${r.priority},${r.created}" ) def update(r: RNotificationChannelGotify): ConnectionIO[Int] = @@ -64,7 +66,8 @@ object RNotificationChannelGotify { DML.set( T.url.setTo(r.url), T.appKey.setTo(r.appKey), - T.priority.setTo(r.priority) + T.priority.setTo(r.priority), + T.name.setTo(r.name) ) ) diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala index b02108c2..9c3d6ad0 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala @@ -18,6 +18,7 @@ import doobie.implicits._ final case class RNotificationChannelHttp( id: Ident, uid: Ident, + name: Option[String], url: LenientUri, created: Timestamp ) { @@ -32,11 +33,12 @@ object RNotificationChannelHttp { val id = Column[Ident]("id", this) val uid = Column[Ident]("uid", this) + val name = Column[String]("name", this) val url = Column[LenientUri]("url", this) val created = Column[Timestamp]("created", this) val all: NonEmptyList[Column[_]] = - NonEmptyList.of(id, uid, url, created) + NonEmptyList.of(id, uid, name, url, created) } val T: Table = Table(None) @@ -47,10 +49,14 @@ object RNotificationChannelHttp { run(select(T.all), from(T), T.id === id).query[RNotificationChannelHttp].option def insert(r: RNotificationChannelHttp): ConnectionIO[Int] = - DML.insert(T, T.all, sql"${r.id},${r.uid},${r.url},${r.created}") + DML.insert(T, T.all, sql"${r.id},${r.uid},${r.name},${r.url},${r.created}") def update(r: RNotificationChannelHttp): ConnectionIO[Int] = - DML.update(T, T.id === r.id && T.uid === r.uid, DML.set(T.url.setTo(r.url))) + DML.update( + T, + T.id === r.id && T.uid === r.uid, + DML.set(T.url.setTo(r.url), T.name.setTo(r.name)) + ) def getByAccount(account: AccountId): ConnectionIO[Vector[RNotificationChannelHttp]] = { val user = RUser.as("u") diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala index db26b458..6c11eb0c 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala @@ -19,6 +19,7 @@ import emil.MailAddress final case class RNotificationChannelMail( id: Ident, uid: Ident, + name: Option[String], connection: Ident, recipients: List[MailAddress], created: Timestamp @@ -34,12 +35,13 @@ object RNotificationChannelMail { val id = Column[Ident]("id", this) val uid = Column[Ident]("uid", this) + val name = Column[String]("name", this) val connection = Column[Ident]("conn_id", this) val recipients = Column[List[MailAddress]]("recipients", this) val created = Column[Timestamp]("created", this) val all: NonEmptyList[Column[_]] = - NonEmptyList.of(id, uid, connection, recipients, created) + NonEmptyList.of(id, uid, name, connection, recipients, created) } val T: Table = Table(None) @@ -49,7 +51,7 @@ object RNotificationChannelMail { DML.insert( T, T.all, - sql"${r.id},${r.uid},${r.connection},${r.recipients},${r.created}" + sql"${r.id},${r.uid},${r.name},${r.connection},${r.recipients},${r.created}" ) def update(r: RNotificationChannelMail): ConnectionIO[Int] = @@ -58,7 +60,8 @@ object RNotificationChannelMail { T.id === r.id && T.uid === r.uid, DML.set( T.connection.setTo(r.connection), - T.recipients.setTo(r.recipients.toList) + T.recipients.setTo(r.recipients.toList), + T.name.setTo(r.name) ) ) diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala index 1ba94ba5..386f9910 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala @@ -18,6 +18,7 @@ import doobie.implicits._ final case class RNotificationChannelMatrix( id: Ident, uid: Ident, + name: Option[String], homeServer: LenientUri, roomId: String, accessToken: Password, @@ -34,6 +35,7 @@ object RNotificationChannelMatrix { val id = Column[Ident]("id", this) val uid = Column[Ident]("uid", this) + val name = Column[String]("name", this) val homeServer = Column[LenientUri]("home_server", this) val roomId = Column[String]("room_id", this) val accessToken = Column[Password]("access_token", this) @@ -41,7 +43,16 @@ object RNotificationChannelMatrix { val created = Column[Timestamp]("created", this) val all: NonEmptyList[Column[_]] = - NonEmptyList.of(id, uid, homeServer, roomId, accessToken, messageType, created) + NonEmptyList.of( + id, + uid, + name, + homeServer, + roomId, + accessToken, + messageType, + created + ) } val T: Table = Table(None) def as(alias: String): Table = Table(Some(alias)) @@ -50,7 +61,7 @@ object RNotificationChannelMatrix { DML.insert( T, T.all, - sql"${r.id},${r.uid},${r.homeServer},${r.roomId},${r.accessToken},${r.messageType},${r.created}" + sql"${r.id},${r.uid},${r.name},${r.homeServer},${r.roomId},${r.accessToken},${r.messageType},${r.created}" ) def update(r: RNotificationChannelMatrix): ConnectionIO[Int] = @@ -61,7 +72,8 @@ object RNotificationChannelMatrix { T.homeServer.setTo(r.homeServer), T.roomId.setTo(r.roomId), T.accessToken.setTo(r.accessToken), - T.messageType.setTo(r.messageType) + T.messageType.setTo(r.messageType), + T.name.setTo(r.name) ) )