From ee4044de29dd49a9078d6a132410c70cfd448557 Mon Sep 17 00:00:00 2001 From: Jhoan Munoz Date: Wed, 24 Jan 2024 16:16:34 +0000 Subject: [PATCH] Pivotal ID # 186547510: Configurable Notifications E-Mail Subject - Use the configuration mechanism to set the e-mail subject - Use constructor binding for the handlers app configuration in order to avoid missing properties - Remove unused properties - Improve tests --- .../templates/NotificationSubjectModel.kt | 14 +++ .../service/RtNotificationService.kt | 14 ++- .../resources/templates/subject/BioImages.txt | 1 + .../resources/templates/subject/Default.txt | 1 + .../service/RtNotificationServiceTest.kt | 92 ++++++++++--------- .../properties/NotificationProperties.kt | 29 +++--- .../handlers/config/ApplicationConfig.kt | 2 + .../handlers/config/ApplicationProperties.kt | 14 +-- 8 files changed, 98 insertions(+), 69 deletions(-) create mode 100644 submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/integration/templates/NotificationSubjectModel.kt create mode 100644 submission/notifications/src/main/resources/templates/subject/BioImages.txt create mode 100644 submission/notifications/src/main/resources/templates/subject/Default.txt diff --git a/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/integration/templates/NotificationSubjectModel.kt b/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/integration/templates/NotificationSubjectModel.kt new file mode 100644 index 0000000000..0a84554d30 --- /dev/null +++ b/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/integration/templates/NotificationSubjectModel.kt @@ -0,0 +1,14 @@ +package ebi.ac.uk.notifications.integration.templates + +import ebi.ac.uk.notifications.integration.model.NotificationTemplate +import ebi.ac.uk.notifications.integration.model.NotificationTemplateModel + +internal class NotificationSubjectTemplate(content: String) : NotificationTemplate(content) + +internal class NotificationSubjectModel( + private val accNo: String +) : NotificationTemplateModel { + override fun getParams(): List> = listOf( + "ACC_NO" to accNo, + ) +} diff --git a/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/service/RtNotificationService.kt b/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/service/RtNotificationService.kt index 197cbd532d..6667074728 100644 --- a/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/service/RtNotificationService.kt +++ b/submission/notifications/src/main/kotlin/ebi/ac/uk/notifications/service/RtNotificationService.kt @@ -3,6 +3,8 @@ package ebi.ac.uk.notifications.service import ebi.ac.uk.base.EMPTY import ebi.ac.uk.extended.model.ExtSubmission import ebi.ac.uk.extended.model.computedTitle +import ebi.ac.uk.notifications.integration.templates.NotificationSubjectModel +import ebi.ac.uk.notifications.integration.templates.NotificationSubjectTemplate import ebi.ac.uk.notifications.integration.templates.SubmissionReleaseModel import ebi.ac.uk.notifications.integration.templates.SubmissionReleaseTemplate import ebi.ac.uk.notifications.integration.templates.SuccessfulSubmissionModel @@ -11,6 +13,7 @@ import ebi.ac.uk.notifications.util.TemplateLoader import ebi.ac.uk.util.date.toStringDate internal const val FROM = "biostudies@ebi.ac.uk" +internal const val EMAIL_SUBJECT_TEMPLATE = "subject/%s.txt" internal const val SUBMISSION_RELEASE_TEMPLATE = "release/%s.txt" internal const val SUCCESSFUL_SUBMISSION_TEMPLATE = "submission/%s.txt" internal const val SUCCESSFUL_RESUBMISSION_TEMPLATE = "resubmission/%s.txt" @@ -20,7 +23,7 @@ class RtNotificationService( private val rtTicketService: RtTicketService ) { fun notifySuccessfulSubmission(sub: ExtSubmission, ownerFullName: String, uiUrl: String, stUrl: String) { - val subject = "BioStudies Submission - ${sub.accNo}" + val subject = notificationSubject(sub) val template = if (sub.version == 1) SUCCESSFUL_SUBMISSION_TEMPLATE else SUCCESSFUL_RESUBMISSION_TEMPLATE val model = successfulSubmissionModel(sub, uiUrl, stUrl, ownerFullName) val content = SuccessfulSubmissionTemplate(templateLoader.loadTemplateOrDefault(sub, template)).render(model) @@ -29,7 +32,7 @@ class RtNotificationService( } fun notifySubmissionRelease(sub: ExtSubmission, ownerFullName: String, uiUrl: String, stUrl: String) { - val subject = "BioStudies Submission - ${sub.accNo}" + val subject = notificationSubject(sub) val model = submissionReleaseModel(sub, uiUrl, stUrl, ownerFullName) val template = templateLoader.loadTemplateOrDefault(sub, SUBMISSION_RELEASE_TEMPLATE) val content = SubmissionReleaseTemplate(template).render(model) @@ -37,6 +40,13 @@ class RtNotificationService( rtTicketService.saveRtTicket(sub.accNo, subject, sub.owner, content) } + private fun notificationSubject(sub: ExtSubmission): String { + val model = NotificationSubjectModel(sub.accNo) + val template = templateLoader.loadTemplateOrDefault(sub, EMAIL_SUBJECT_TEMPLATE) + + return NotificationSubjectTemplate(template).render(model) + } + companion object { private fun submissionReleaseModel( submission: ExtSubmission, diff --git a/submission/notifications/src/main/resources/templates/subject/BioImages.txt b/submission/notifications/src/main/resources/templates/subject/BioImages.txt new file mode 100644 index 0000000000..be7ad3c69c --- /dev/null +++ b/submission/notifications/src/main/resources/templates/subject/BioImages.txt @@ -0,0 +1 @@ +BioImage Archive Submission - ${ACC_NO} \ No newline at end of file diff --git a/submission/notifications/src/main/resources/templates/subject/Default.txt b/submission/notifications/src/main/resources/templates/subject/Default.txt new file mode 100644 index 0000000000..78e90ed350 --- /dev/null +++ b/submission/notifications/src/main/resources/templates/subject/Default.txt @@ -0,0 +1 @@ +BioStudies Submission - ${ACC_NO} \ No newline at end of file diff --git a/submission/notifications/src/test/kotlin/ebi/ac/uk/notifications/service/RtNotificationServiceTest.kt b/submission/notifications/src/test/kotlin/ebi/ac/uk/notifications/service/RtNotificationServiceTest.kt index 9d5409a36d..3cdf8c92f0 100644 --- a/submission/notifications/src/test/kotlin/ebi/ac/uk/notifications/service/RtNotificationServiceTest.kt +++ b/submission/notifications/src/test/kotlin/ebi/ac/uk/notifications/service/RtNotificationServiceTest.kt @@ -38,7 +38,7 @@ internal class RtNotificationServiceTest( @Test fun `when no released but release date`() { testNotification( - submission = testSubmission( + submission = testSubmission.copy( releaseTime = OffsetDateTime.of(2019, 9, 21, 10, 30, 34, 15, ZoneOffset.UTC), released = false ), @@ -62,7 +62,7 @@ internal class RtNotificationServiceTest( @Test fun `when no released no release date`() { testNotification( - submission = testSubmission(releaseTime = null, released = false), + submission = testSubmission.copy(releaseTime = null, released = false), """ Dear owner@mail.org, @@ -83,7 +83,7 @@ internal class RtNotificationServiceTest( @Test fun `when released`() { testNotification( - submission = testSubmission(released = true), + submission = testSubmission.copy(released = true), """ Dear owner@mail.org, @@ -104,7 +104,7 @@ internal class RtNotificationServiceTest( @Test fun `when submission title`() { testNotification( - submission = testSubmission(title = "Sub Title", version = 1), + submission = testSubmission.copy(title = "Sub Title"), """ Dear owner@mail.org, @@ -125,7 +125,7 @@ internal class RtNotificationServiceTest( @Test fun `when section title`() { testNotification( - submission = testSubmission(title = "Sect Title", version = 1), + submission = testSubmission.copy(title = "Sect Title"), """ Dear owner@mail.org, @@ -149,10 +149,15 @@ internal class RtNotificationServiceTest( every { loader.loadTemplateOrDefault(submission, SUCCESSFUL_SUBMISSION_TEMPLATE) } returns asText("/templates/submission/Default.txt") + + every { + loader.loadTemplateOrDefault(submission, EMAIL_SUBJECT_TEMPLATE) + } returns asText("/templates/subject/BioImages.txt") + every { ticketService.saveRtTicket( "S-TEST1", - "BioStudies Submission - S-TEST1", + "BioImage Archive Submission - S-TEST1", "owner@mail.org", capture(slot) ) @@ -169,7 +174,7 @@ internal class RtNotificationServiceTest( @Test fun `when released`() { testNotification( - submission = testSubmission(released = true, version = 2), + submission = testSubmission.copy(released = true, version = 2, collections = listOf()), """ Dear owner@mail.org, @@ -191,6 +196,11 @@ internal class RtNotificationServiceTest( every { loader.loadTemplateOrDefault(submission, SUCCESSFUL_RESUBMISSION_TEMPLATE) } returns asText("/templates/resubmission/Default.txt") + + every { + loader.loadTemplateOrDefault(submission, EMAIL_SUBJECT_TEMPLATE) + } returns asText("/templates/subject/Default.txt") + every { ticketService.saveRtTicket( "S-TEST1", @@ -212,7 +222,7 @@ internal class RtNotificationServiceTest( @Test fun `when no title`() { testNotification( - submission = testSubmission(released = true), + submission = testSubmission.copy(released = true), """ Dear owner@mail.org, @@ -233,7 +243,7 @@ internal class RtNotificationServiceTest( @Test fun `when submission title`() { testNotification( - submission = testSubmission(title = "Sub Title", version = 1), + submission = testSubmission.copy(title = "Sub Title"), """ Dear owner@mail.org, @@ -254,7 +264,7 @@ internal class RtNotificationServiceTest( @Test fun `when section title`() { testNotification( - submission = testSubmission(title = "Sect Title", version = 1), + submission = testSubmission.copy(title = "Sect Title"), """ Dear owner@mail.org, @@ -278,10 +288,15 @@ internal class RtNotificationServiceTest( every { loader.loadTemplateOrDefault(submission, SUBMISSION_RELEASE_TEMPLATE) } returns asText("/templates/release/Default.txt") + + every { + loader.loadTemplateOrDefault(submission, EMAIL_SUBJECT_TEMPLATE) + } returns asText("/templates/subject/BioImages.txt") + every { ticketService.saveRtTicket( "S-TEST1", - "BioStudies Submission - S-TEST1", + "BioImage Archive Submission - S-TEST1", "owner@mail.org", capture(slot) ) @@ -296,35 +311,28 @@ internal class RtNotificationServiceTest( private fun asText(path: String): String = object {}.javaClass.getResource(path)!!.readText() - private fun testSubmission( - title: String? = null, - secTitle: String? = null, - version: Int = 1, - released: Boolean = false, - releaseTime: OffsetDateTime? = OffsetDateTime.of(2019, 9, 21, 10, 30, 34, 15, ZoneOffset.UTC) - ): ExtSubmission = ExtSubmission( - accNo = "S-TEST1", - version = version, - schemaVersion = "1.0", - owner = "owner@mail.org", - submitter = "submitter@mail.org", - title = title, - doi = "10.983/S-TEST1", - method = ExtSubmissionMethod.PAGE_TAB, - relPath = "/a/rel/path", - rootPath = "/a/root/path", - released = released, - secretKey = "a-secret-key", - releaseTime = releaseTime, - modificationTime = OffsetDateTime.of(2019, 9, 20, 10, 30, 34, 15, ZoneOffset.UTC), - creationTime = OffsetDateTime.of(2019, 9, 19, 10, 30, 34, 15, ZoneOffset.UTC), - attributes = listOf(ExtAttribute("AttachTo", "BioImages")), - tags = listOf(ExtTag("component", "web")), - collections = listOf(ExtCollection("BioImages")), - section = ExtSection( - type = "Study", - attributes = secTitle?.let { listOf(ExtAttribute(name = "Title", value = it)) } ?: listOf() - ), - storageMode = StorageMode.NFS - ) + companion object { + val testSubmission = ExtSubmission( + accNo = "S-TEST1", + version = 1, + schemaVersion = "1.0", + owner = "owner@mail.org", + submitter = "submitter@mail.org", + title = null, + doi = "10.983/S-TEST1", + method = ExtSubmissionMethod.PAGE_TAB, + relPath = "/a/rel/path", + rootPath = "/a/root/path", + released = false, + secretKey = "a-secret-key", + releaseTime = OffsetDateTime.of(2019, 9, 21, 10, 30, 34, 15, ZoneOffset.UTC), + modificationTime = OffsetDateTime.of(2019, 9, 20, 10, 30, 34, 15, ZoneOffset.UTC), + creationTime = OffsetDateTime.of(2019, 9, 19, 10, 30, 34, 15, ZoneOffset.UTC), + attributes = listOf(ExtAttribute("AttachTo", "BioImages")), + tags = listOf(ExtTag("component", "web")), + collections = listOf(ExtCollection("BioImages")), + section = ExtSection(type = "Study"), + storageMode = StorageMode.NFS, + ) + } } diff --git a/submission/submission-config/src/main/kotlin/ac/uk/ebi/biostd/common/properties/NotificationProperties.kt b/submission/submission-config/src/main/kotlin/ac/uk/ebi/biostd/common/properties/NotificationProperties.kt index 8798345b8d..45b1c43d5d 100644 --- a/submission/submission-config/src/main/kotlin/ac/uk/ebi/biostd/common/properties/NotificationProperties.kt +++ b/submission/submission-config/src/main/kotlin/ac/uk/ebi/biostd/common/properties/NotificationProperties.kt @@ -1,23 +1,20 @@ package ac.uk.ebi.biostd.common.properties -import org.springframework.boot.context.properties.NestedConfigurationProperty import java.util.Properties -class NotificationProperties { - lateinit var smtp: String - lateinit var uiUrl: String - lateinit var stUrl: String - lateinit var slackUrl: String - - @NestedConfigurationProperty - var rt: RtConfig = RtConfig() - +data class NotificationProperties( + val smtp: String, + val uiUrl: String, + val stUrl: String, + val slackUrl: String, + val rt: RtConfig, +) { fun asProperties(): Properties = Properties().apply { setProperty("mail.host", smtp) } } -class RtConfig { - lateinit var host: String - lateinit var queue: String - lateinit var user: String - lateinit var password: String -} +data class RtConfig( + val host: String, + val queue: String, + val user: String, + val password: String, +) diff --git a/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationConfig.kt b/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationConfig.kt index d27478a2e5..65e651d05f 100644 --- a/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationConfig.kt +++ b/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationConfig.kt @@ -17,6 +17,7 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer +import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Import @@ -27,6 +28,7 @@ import uk.ac.ebi.extended.serialization.service.ExtSerializationService @Configuration @Import(NotificationPersistenceConfig::class) +@EnableConfigurationProperties(ApplicationProperties::class) class Listeners { @Bean fun logListener(): LogSubmissionListener = LogSubmissionListener() diff --git a/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationProperties.kt b/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationProperties.kt index 628b1e1f23..0fec9a3d34 100644 --- a/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationProperties.kt +++ b/submission/submission-handlers/src/main/kotlin/ac/uk/ebi/biostd/handlers/config/ApplicationProperties.kt @@ -2,14 +2,10 @@ package ac.uk.ebi.biostd.handlers.config import ac.uk.ebi.biostd.common.properties.NotificationProperties import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.boot.context.properties.NestedConfigurationProperty -import org.springframework.stereotype.Component +import org.springframework.boot.context.properties.ConstructorBinding -@Component @ConfigurationProperties(prefix = "app") -class ApplicationProperties { - lateinit var baseInstanceUrl: String - - @NestedConfigurationProperty - var notifications: NotificationProperties = NotificationProperties() -} +@ConstructorBinding +data class ApplicationProperties( + val notifications: NotificationProperties, +)