diff --git a/ebms-provider/build.gradle.kts b/ebms-provider/build.gradle.kts index a7c9b670f..bd1bd61ec 100644 --- a/ebms-provider/build.gradle.kts +++ b/ebms-provider/build.gradle.kts @@ -32,6 +32,12 @@ tasks { } } +tasks.withType().all { + compilerOptions { + freeCompilerArgs = listOf("-opt-in=kotlin.uuid.ExperimentalUuidApi") + } +} + dependencies { implementation(project(":felles")) implementation(project(":ebxml-processing-model")) diff --git a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt index 89c576d26..3391566b2 100644 --- a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt +++ b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt @@ -17,6 +17,8 @@ import kotlinx.coroutines.awaitCancellation import no.nav.emottak.ebms.configuration.config import no.nav.emottak.ebms.processing.ProcessingService import no.nav.emottak.ebms.sendin.SendInService +import no.nav.emottak.ebms.util.EventRegistrationService +import no.nav.emottak.ebms.util.EventRegistrationServiceImpl import no.nav.emottak.ebms.validation.DokumentValidator import no.nav.emottak.utils.kafka.client.EventPublisherClient import no.nav.emottak.utils.kafka.service.EventLoggingService @@ -38,7 +40,8 @@ fun main() = SuspendApp { val sendInService = SendInService(sendInClient) val kafkaPublisherClient = EventPublisherClient(config().kafka) - val eventLoggingService = EventLoggingService(kafkaPublisherClient) + val eventLoggingService = EventLoggingService(config().eventLogging, kafkaPublisherClient) + val eventRegistrationService = EventRegistrationServiceImpl(eventLoggingService) result { resourceScope { @@ -50,7 +53,7 @@ fun main() = SuspendApp { dokumentValidator, processingService, sendInService, - eventLoggingService + eventRegistrationService ) } ).also { it.engineConfig.maxChunkSize = 100000 } @@ -70,7 +73,7 @@ fun Application.ebmsProviderModule( validator: DokumentValidator, processing: ProcessingService, sendInService: SendInService, - eventLoggingService: EventLoggingService + eventRegistrationService: EventRegistrationService ) { val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT) @@ -84,6 +87,6 @@ fun Application.ebmsProviderModule( registerPrometheusEndpoint(appMicrometerRegistry) registerNavCheckStatus() - postEbmsSync(validator, processing, sendInService, eventLoggingService) + postEbmsSync(validator, processing, sendInService, eventRegistrationService) } } diff --git a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/EbmsDocumentExchange.kt b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/EbmsDocumentExchange.kt index 49643feea..90c2b588c 100644 --- a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/EbmsDocumentExchange.kt +++ b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/EbmsDocumentExchange.kt @@ -35,7 +35,6 @@ import no.nav.emottak.message.xml.getDocumentBuilder import java.io.ByteArrayInputStream import java.nio.charset.StandardCharsets import java.util.Base64 -import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid fun PartData.payload(clearText: Boolean = false): ByteArray { @@ -70,7 +69,6 @@ fun Headers.actuallyUsefulToString(): String { return sb.toString() } -@OptIn(ExperimentalUuidApi::class) @Throws(MimeValidationException::class) suspend fun ApplicationCall.receiveEbmsDokument(): EbMSDocument { log.info("Parsing message with Message-Id: ${request.header(SMTPHeaders.MESSAGE_ID)}") diff --git a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/Routes.kt b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/Routes.kt index fd4e775aa..aba749408 100644 --- a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/Routes.kt +++ b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/Routes.kt @@ -10,6 +10,7 @@ import no.nav.emottak.constants.SMTPHeaders import no.nav.emottak.ebms.model.signer import no.nav.emottak.ebms.processing.ProcessingService import no.nav.emottak.ebms.sendin.SendInService +import no.nav.emottak.ebms.util.EventRegistrationService import no.nav.emottak.ebms.util.marker import no.nav.emottak.ebms.validation.DokumentValidator import no.nav.emottak.ebms.validation.MimeValidationException @@ -24,20 +25,15 @@ import no.nav.emottak.message.model.PayloadProcessing import no.nav.emottak.message.model.SignatureDetails import no.nav.emottak.util.marker import no.nav.emottak.util.retrieveLoggableHeaderPairs -import no.nav.emottak.utils.common.parseOrGenerateUuid -import no.nav.emottak.utils.kafka.model.Event import no.nav.emottak.utils.kafka.model.EventType -import no.nav.emottak.utils.kafka.service.EventLoggingService import no.nav.emottak.utils.serialization.toEventDataJson -import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid -@OptIn(ExperimentalUuidApi::class) fun Route.postEbmsSync( validator: DokumentValidator, processingService: ProcessingService, sendInService: SendInService, - eventLoggingService: EventLoggingService + eventRegistrationService: EventRegistrationService ): Route = post("/ebms/sync") { log.info("Receiving synchronous request") @@ -47,7 +43,9 @@ fun Route.postEbmsSync( call.request.validateMime() ebMSDocument = call.receiveEbmsDokument() log.info(ebMSDocument.messageHeader().marker(loggableHeaders), "Melding mottatt") - eventLoggingService.registerEvent( + + eventRegistrationService.registerEventMessageDetails(ebMSDocument) + eventRegistrationService.registerEvent( EventType.MESSAGE_RECEIVED_VIA_HTTP, ebMSDocument ) @@ -119,7 +117,7 @@ fun Route.postEbmsSync( } ) log.info(it.first.marker(), "Melding ferdig behandlet og svar returnert") - eventLoggingService.registerEvent( + eventRegistrationService.registerEvent( EventType.MESSAGE_SENT_VIA_HTTP, it.first.toEbmsDokument() ) @@ -133,7 +131,7 @@ fun Route.postEbmsSync( } log.info(ebmsMessage.marker(), "Created MessageError response") - eventLoggingService.registerEvent( + eventRegistrationService.registerEvent( EventType.ERROR_WHILE_SENDING_MESSAGE_VIA_HTTP, ebMSDocument, ebmsException.toEventDataJson() @@ -145,7 +143,7 @@ fun Route.postEbmsSync( } catch (ex: Exception) { log.error(ebmsMessage.marker(), "Unknown error during message processing: ${ex.message}", ex) - eventLoggingService.registerEvent( + eventRegistrationService.registerEvent( EventType.ERROR_WHILE_SENDING_MESSAGE_VIA_HTTP, ebMSDocument, ex.toEventDataJson() @@ -157,32 +155,3 @@ fun Route.postEbmsSync( ) } } - -@OptIn(ExperimentalUuidApi::class) -suspend fun EventLoggingService.registerEvent( - eventType: EventType, - ebMSDocument: EbMSDocument, - eventData: String = "" -) { - log.debug("Event reg. test: Registering event for requestId: ${ebMSDocument.requestId}") - - try { - val requestId = ebMSDocument.requestId.parseOrGenerateUuid() - - log.debug("Event reg. test: RequestId: $requestId") - - val event = Event( - eventType = eventType, - requestId = requestId, - contentId = "", - messageId = ebMSDocument.transform().messageId, - eventData = eventData - ) - - log.debug("Event reg. test: Publishing event: $event") - this.logEvent(event) - log.debug("Event reg. test: Event published successfully") - } catch (e: Exception) { - log.error("Event reg. test: Error while registering event: ${e.message}", e) - } -} diff --git a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/configuration/Config.kt b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/configuration/Config.kt index e7848dfe3..f4cae7309 100644 --- a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/configuration/Config.kt +++ b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/configuration/Config.kt @@ -1,9 +1,11 @@ package no.nav.emottak.ebms.configuration +import no.nav.emottak.utils.config.EventLogging import no.nav.emottak.utils.config.Kafka data class Config( val kafka: Kafka, + val eventLogging: EventLogging, val kafkaSignalReceiver: KafkaSignalReceiver, val kafkaSignalProducer: KafkaSignalProducer, val kafkaPayloadReceiver: KafkaPayloadReceiver, diff --git a/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/util/EventRegistration.kt b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/util/EventRegistration.kt new file mode 100644 index 000000000..fedfa3459 --- /dev/null +++ b/ebms-provider/src/main/kotlin/no/nav/emottak/ebms/util/EventRegistration.kt @@ -0,0 +1,107 @@ +package no.nav.emottak.ebms.util + +import no.nav.emottak.ebms.log +import no.nav.emottak.message.model.EbMSDocument +import no.nav.emottak.message.model.PartyId +import no.nav.emottak.utils.common.parseOrGenerateUuid +import no.nav.emottak.utils.kafka.model.EbmsMessageDetails +import no.nav.emottak.utils.kafka.model.Event +import no.nav.emottak.utils.kafka.model.EventType +import no.nav.emottak.utils.kafka.service.EventLoggingService + +interface EventRegistrationService { + suspend fun registerEvent( + eventType: EventType, + ebMSDocument: EbMSDocument, + eventData: String = "{}" + ) + + suspend fun registerEventMessageDetails(ebMSDocument: EbMSDocument) + + companion object { + fun serializePartyId(partyIDs: List): String { + val partyId = partyIDs.firstOrNull { it.type == "orgnummer" } + ?: partyIDs.firstOrNull { it.type == "HER" } + ?: partyIDs.firstOrNull { it.type == "ENH" } + ?: partyIDs.first() + + return "${partyId.type}:${partyId.value}" + } + } +} + +class EventRegistrationServiceImpl( + private val eventLoggingService: EventLoggingService +) : EventRegistrationService { + override suspend fun registerEvent( + eventType: EventType, + ebMSDocument: EbMSDocument, + eventData: String + ) { + log.debug("Registering event for requestId: ${ebMSDocument.requestId}") + + try { + val requestId = ebMSDocument.requestId.parseOrGenerateUuid() + + val event = Event( + eventType = eventType, + requestId = requestId, + contentId = "", + messageId = ebMSDocument.transform().messageId, + eventData = eventData + ) + log.debug("Event reg. test: Publishing event: $event") + + eventLoggingService.logEvent(event) + log.debug("Event reg. test: Event published successfully") + } catch (e: Exception) { + log.error("Event reg. test: Error while registering event: ${e.message}", e) + } + } + + override suspend fun registerEventMessageDetails(ebMSDocument: EbMSDocument) { + log.debug("Registering message with requestId: ${ebMSDocument.requestId}") + + try { + val ebmsMessage = ebMSDocument.transform() + val requestId = ebmsMessage.requestId.parseOrGenerateUuid() + + val ebmsMessageDetails = EbmsMessageDetails( + requestId = requestId, + cpaId = ebmsMessage.cpaId, + conversationId = ebmsMessage.conversationId, + messageId = ebmsMessage.messageId, + refToMessageId = ebmsMessage.refToMessageId, + fromPartyId = EventRegistrationService.serializePartyId(ebmsMessage.addressing.from.partyId), + fromRole = ebmsMessage.addressing.from.role, + toPartyId = EventRegistrationService.serializePartyId(ebmsMessage.addressing.to.partyId), + toRole = ebmsMessage.addressing.to.role, + service = ebmsMessage.addressing.service, + action = ebmsMessage.addressing.action, + refParam = null, + sender = null, + sentAt = ebmsMessage.sentAt + ) + log.debug("Publishing message details: $ebmsMessageDetails") + + eventLoggingService.logMessageDetails(ebmsMessageDetails) + log.debug("Message details published successfully") + } catch (e: Exception) { + log.error("Error while registering message details: ${e.message}", e) + } + } +} + +class EventRegistrationServiceFake : EventRegistrationService { + override suspend fun registerEvent( + eventType: EventType, + ebMSDocument: EbMSDocument, + eventData: String + ) { + log.debug("Registering event $eventType for ebMSDocument: $ebMSDocument and eventData: $eventData") + } + + override suspend fun registerEventMessageDetails(ebMSDocument: EbMSDocument) { + log.debug("Registering message details for ebMSDocument: $ebMSDocument") + } +} diff --git a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRoutFellesIT.kt b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRoutFellesIT.kt index 68575ebbf..fc470d205 100644 --- a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRoutFellesIT.kt +++ b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRoutFellesIT.kt @@ -14,6 +14,7 @@ import io.mockk.coVerify import io.mockk.mockk import no.nav.emottak.ebms.processing.ProcessingService import no.nav.emottak.ebms.sendin.SendInService +import no.nav.emottak.ebms.util.EventRegistrationServiceFake import no.nav.emottak.ebms.validation.DokumentValidator import no.nav.emottak.ebms.validation.MimeHeaders import no.nav.emottak.message.ebxml.errorList @@ -27,7 +28,6 @@ import no.nav.emottak.message.model.ValidationResult import no.nav.emottak.message.xml.xmlMarshaller import no.nav.emottak.util.decodeBase64 import no.nav.emottak.utils.environment.getEnvVar -import no.nav.emottak.utils.kafka.service.EventLoggingService import org.apache.xml.security.algorithms.MessageDigestAlgorithm import org.apache.xml.security.signature.XMLSignature import org.junit.jupiter.api.Assertions @@ -39,7 +39,7 @@ abstract class EbmsRoutFellesIT(val endpoint: String) { val validMultipartRequest = validMultipartRequest() val processingService = mockk() - val eventLoggingService = mockk() + val eventRegistrationService = EventRegistrationServiceFake() val mockProcessConfig = ProcessConfig( true, true, @@ -69,7 +69,7 @@ abstract class EbmsRoutFellesIT(val endpoint: String) { } routing { - postEbmsSync(dokumentValidator, processingService, SendInService(sendInClient), eventLoggingService) + postEbmsSync(dokumentValidator, processingService, SendInService(sendInClient), eventRegistrationService) } } externalServices { diff --git a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRouteSyncIT.kt b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRouteSyncIT.kt index 02207ceda..bfd50cbe5 100644 --- a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRouteSyncIT.kt +++ b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/EbmsRouteSyncIT.kt @@ -39,12 +39,10 @@ import no.nav.emottak.utils.environment.getEnvVar import org.apache.xml.security.algorithms.MessageDigestAlgorithm import org.apache.xml.security.signature.XMLSignature import org.junit.jupiter.api.Test -import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid private const val SYNC_PATH = "/ebms/sync" -@OptIn(ExperimentalUuidApi::class) class EbmsRouteSyncIT : EbmsRoutFellesIT(SYNC_PATH) { fun testSyncApp(testBlock: suspend ApplicationTestBuilder.() -> T) = testApplication { @@ -69,7 +67,7 @@ class EbmsRouteSyncIT : EbmsRoutFellesIT(SYNC_PATH) { incomingMessage } routing { - postEbmsSync(dokumentValidator, processingService, SendInService(sendInClient), eventLoggingService) + postEbmsSync(dokumentValidator, processingService, SendInService(sendInClient), eventRegistrationService) } } externalServices { @@ -131,7 +129,6 @@ class EbmsRouteSyncIT : EbmsRoutFellesIT(SYNC_PATH) { testBlock() } - @OptIn(ExperimentalUuidApi::class) @Test fun `Valid payload request should trigger processing and validation on way out`() = testSyncApp { mockkStatic(EbMSDocument::signer) @@ -149,7 +146,6 @@ class EbmsRouteSyncIT : EbmsRoutFellesIT(SYNC_PATH) { println("----=_Part_" + Uuid.random().toString()) } - @OptIn(ExperimentalUuidApi::class) @Test fun `Feilmelding fra fagsystemet må propageres til brukeren`() = testSyncApp { val soapFault = "SOAP-ENV:ServerNoe gikk galt i fagsystemet" diff --git a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/test/IntegrasjonsTest.kt b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/test/IntegrasjonsTest.kt index f218204d7..633ac53cd 100644 --- a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/test/IntegrasjonsTest.kt +++ b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/test/IntegrasjonsTest.kt @@ -12,7 +12,6 @@ import io.ktor.server.engine.embeddedServer import io.ktor.server.netty.Netty import io.ktor.server.testing.testApplication import io.mockk.clearAllMocks -import io.mockk.mockk import kotlinx.coroutines.runBlocking import no.nav.emottak.constants.SMTPHeaders import no.nav.emottak.cpa.cpaApplicationModule @@ -28,9 +27,9 @@ import no.nav.emottak.ebms.processing.ProcessingService import no.nav.emottak.ebms.scopedAuthHttpClient import no.nav.emottak.ebms.sendin.SendInService import no.nav.emottak.ebms.testConfiguration +import no.nav.emottak.ebms.util.EventRegistrationServiceFake import no.nav.emottak.ebms.validation.DokumentValidator import no.nav.emottak.ebms.validation.MimeHeaders -import no.nav.emottak.utils.kafka.service.EventLoggingService import no.nav.security.mock.oauth2.MockOAuth2Server import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions @@ -47,7 +46,7 @@ open class EndToEndTest { val mockOAuth2Server = MockOAuth2Server().also { it.start(port = 3344) } val ebmsProviderUrl = "http://localhost:$portnoEbmsProvider" val cpaRepoUrl = "http://localhost:$portnoCpaRepo" - val eventLoggingService = mockk() + val eventRegistrationService = EventRegistrationServiceFake() // TODO Start mailserver og payload processor val cpaRepoDbContainer: PostgreSQLContainer @@ -86,7 +85,7 @@ open class EndToEndTest { ebmsProviderServer = embeddedServer( Netty, port = portnoEbmsProvider, - module = { ebmsProviderModule(dokumentValidator, processingService, sendInService, eventLoggingService) } + module = { ebmsProviderModule(dokumentValidator, processingService, sendInService, eventRegistrationService) } ).also { it.start() }.engine @@ -105,7 +104,7 @@ class IntegrasjonsTest : EndToEndTest() { @Test fun basicEndpointTest() = testApplication { - application { ebmsProviderModule(dokumentValidator, processingService, sendInService, eventLoggingService) } + application { ebmsProviderModule(dokumentValidator, processingService, sendInService, eventRegistrationService) } val response = client.get("/") Assertions.assertEquals(HttpStatusCode.OK, response.status) Assertions.assertEquals("{\"status\":\"Hello\"}", response.bodyAsText()) diff --git a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/validation/MimeValidationIT.kt b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/validation/MimeValidationIT.kt index 8597e110f..0eea89af8 100644 --- a/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/validation/MimeValidationIT.kt +++ b/ebms-provider/src/test/kotlin/no/nav/emottak/ebms/validation/MimeValidationIT.kt @@ -15,6 +15,7 @@ import no.nav.emottak.ebms.payload import no.nav.emottak.ebms.postEbmsSync import no.nav.emottak.ebms.processing.ProcessingService import no.nav.emottak.ebms.sendin.SendInService +import no.nav.emottak.ebms.util.EventRegistrationServiceFake import no.nav.emottak.ebms.validMultipartRequest import no.nav.emottak.message.ebxml.errorList import no.nav.emottak.message.ebxml.messageHeader @@ -22,7 +23,6 @@ import no.nav.emottak.message.model.ErrorCode import no.nav.emottak.message.model.Feil import no.nav.emottak.message.model.ValidationResult import no.nav.emottak.message.xml.xmlMarshaller -import no.nav.emottak.utils.kafka.service.EventLoggingService import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertTrue @@ -36,7 +36,7 @@ class MimeValidationIT { val validMultipartRequest = validMultipartRequest() val cpaRepoClient = mockk() - val eventLoggingService = mockk() + val eventRegistrationService = EventRegistrationServiceFake() fun mimeTestApp(testBlock: suspend ApplicationTestBuilder.() -> T) = testApplication { application { @@ -44,7 +44,7 @@ class MimeValidationIT { val processingService = mockk() val sendInService = mockk() routing { - postEbmsSync(dokumentValidator, processingService, sendInService, eventLoggingService) + postEbmsSync(dokumentValidator, processingService, sendInService, eventRegistrationService) } } externalServices { diff --git a/settings.gradle.kts b/settings.gradle.kts index b9f6715f1..4674eba84 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,7 +21,7 @@ dependencyResolutionManagement { version("hoplite", "2.8.2") version("logback", "1.5.17") version("logstash", "8.0") - version("emottak-utils", "0.2.2") + version("emottak-utils", "0.2.6") library("bcpkix-jdk18on", "org.bouncycastle", "bcpkix-jdk18on").versionRef("bouncycastle") library("bcprov-jdk18on", "org.bouncycastle", "bcprov-jdk18on").versionRef("bouncycastle")