From 44fd96a55bfc968be1e3c14cc68839d4d01504bf Mon Sep 17 00:00:00 2001 From: Mikael Bjerga <6940327+bjerga@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:27:24 +0100 Subject: [PATCH] =?UTF-8?q?Motta=20=C3=A5pen=20IM=20og=20send=20til=20serv?= =?UTF-8?q?ice=20som=20logger=20(#400)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Motta åpen IM og send til service som logger * Revert publisering av data uten forespoerselId * Liten forbedring på loggmelding * Bruk melding beriket med Redis-data * Spiss ansvaret til funksjon --- aapenimservice/build.gradle.kts | 0 .../aapenimservice/AapenImService.kt | 266 ++++++++++++++++++ .../inntektsmelding/aapenimservice/App.kt | 23 ++ .../inntektsmelding/aapenimservice/Env.kt | 7 + .../inntektsmelding/altinn/TilgangLoeser.kt | 4 +- .../inntektsmelding/api/App.kt | 3 + .../inntektsmelding/api/RedisPoller.kt | 4 +- .../AapenInntektmeldingProducer.kt | 48 ++++ .../AapenInntektmeldingResponse.kt | 13 + .../AapenInntektsmeldingRoute.kt | 124 ++++++++ .../api/auth/Tilgangskontroll.kt | 28 +- .../api/innsending/InnsendingRoute.kt | 3 +- .../api/inntekt/InntektRoute.kt | 2 +- .../api/kvittering/KvitteringRoute.kt | 2 +- .../api/response/JsonErrorResponse.kt | 13 +- .../api/response/RedisTimeoutResponse.kt | 17 +- .../api/tilgang/TilgangProducer.kt | 27 +- .../api/trenger/TrengerRoute.kt | 2 +- .../api/trenger/TrengerRouteKtTest.kt | 2 +- .../inntektsmelding/api/utils/TestUtils.kt | 2 +- .../inntektsmelding/brreg/VirksomhetLoeser.kt | 1 + config/aapenimservice/dev-gcp.yml | 6 + .../helsearbeidsgiver/felles/EventTypes.kt | 6 +- .../no/nav/helsearbeidsgiver/felles/Key.kt | 3 + .../felles/rapidsrivers/Loeser.kt | 42 +-- .../felles/rapidsrivers/model/Behov.kt | 1 + .../nav/helsearbeidsgiver/felles/utils/Log.kt | 4 + gradle.properties | 2 +- .../integrasjonstest/TilgangskontrollIT.kt | 53 +++- .../inntektsmelding/pdl/FulltNavnLoeser.kt | 1 + .../inntektsmelding/tilgangservice/App.kt | 7 +- ...rvice.kt => TilgangForespoerselService.kt} | 41 +-- .../tilgangservice/TilgangOrgService.kt | 163 +++++++++++ ...t.kt => TilgangForespoerselServiceTest.kt} | 13 +- .../inntektservice/TilgangOrgServiceTest.kt | 73 +++++ 35 files changed, 924 insertions(+), 82 deletions(-) create mode 100644 aapenimservice/build.gradle.kts create mode 100644 aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt create mode 100644 aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/App.kt create mode 100644 aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/Env.kt create mode 100644 api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingProducer.kt create mode 100644 api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingResponse.kt create mode 100644 api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektsmeldingRoute.kt create mode 100644 config/aapenimservice/dev-gcp.yml rename tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/{TilgangService.kt => TilgangForespoerselService.kt} (86%) create mode 100644 tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangOrgService.kt rename tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/{TilgangServiceTest.kt => TilgangForespoerselServiceTest.kt} (82%) create mode 100644 tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangOrgServiceTest.kt diff --git a/aapenimservice/build.gradle.kts b/aapenimservice/build.gradle.kts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt new file mode 100644 index 0000000000..a2b4054b3e --- /dev/null +++ b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/AapenImService.kt @@ -0,0 +1,266 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice + +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.json.JsonElement +import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Avsender +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Inntektsmelding +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.Sykmeldt +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding +import no.nav.helsearbeidsgiver.felles.BehovType +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.PersonDato +import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.lesOrNull +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.json.toMap +import no.nav.helsearbeidsgiver.felles.rapidsrivers.FailKanal +import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullDataKanal +import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullEventListener +import no.nav.helsearbeidsgiver.felles.rapidsrivers.composite.CompositeEventListener +import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail +import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.json.toJsonStr +import no.nav.helsearbeidsgiver.utils.json.toPretty +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import no.nav.helsearbeidsgiver.utils.log.logger +import no.nav.helsearbeidsgiver.utils.log.sikkerLogger +import java.time.OffsetDateTime +import java.util.UUID + +// TODO test +class AapenImService( + private val rapid: RapidsConnection, + override val redisStore: RedisStore +) : CompositeEventListener() { + + private val logger = logger() + private val sikkerLogger = sikkerLogger() + + override val event = EventName.AAPEN_IM_MOTTATT + override val startKeys = listOf( + Key.AAPEN_ID, + Key.SKJEMA_INNTEKTSMELDING, + Key.ARBEIDSGIVER_FNR + ) + override val dataKeys = listOf( + Key.VIRKSOMHET, + Key.ARBEIDSTAKER_INFORMASJON, + Key.ARBEIDSGIVER_INFORMASJON, + Key.AAPEN_INNTEKTMELDING, + Key.ER_DUPLIKAT_IM + ) + + private val step1Data = + setOf( + Key.VIRKSOMHET, + Key.ARBEIDSTAKER_INFORMASJON, + Key.ARBEIDSGIVER_INFORMASJON + ) + + init { + StatefullEventListener(rapid, event, redisStore, startKeys, ::onPacket) + StatefullDataKanal(rapid, event, redisStore, dataKeys, ::onPacket) + FailKanal(rapid, event, ::onPacket) + } + + override fun new(melding: Map) { + val transaksjonId = Key.UUID.les(UuidSerializer, melding) + val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding) + val skjema = Key.SKJEMA_INNTEKTSMELDING.les(SkjemaInntektsmelding.serializer(), melding) + val avsenderFnr = Key.ARBEIDSGIVER_FNR.les(String.serializer(), melding) + + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.transaksjonId(transaksjonId), + Log.aapenId(aapenId) + ) { + rapid.publish( + Key.EVENT_NAME to event.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.BEHOV to BehovType.VIRKSOMHET.toJson(), + Key.ORGNRUNDERENHET to skjema.avsender.orgnr.toJson() + ) + + rapid.publish( + Key.EVENT_NAME to event.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.BEHOV to BehovType.FULLT_NAVN.toJson(), + Key.IDENTITETSNUMMER to skjema.sykmeldtFnr.toJson(), + Key.ARBEIDSGIVER_ID to avsenderFnr.toJson() + ) + } + } + + override fun inProgress(melding: Map) { + val transaksjonId = Key.UUID.les(UuidSerializer, melding) + val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding) + + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.transaksjonId(transaksjonId), + Log.aapenId(aapenId) + ) { + if (step1Data.all { it in melding }) { + val skjema = Key.SKJEMA_INNTEKTSMELDING.les(SkjemaInntektsmelding.serializer(), melding) + val orgNavn = Key.VIRKSOMHET.les(String.serializer(), melding) + val sykmeldt = Key.ARBEIDSTAKER_INFORMASJON.les(PersonDato.serializer(), melding) + val avsender = Key.ARBEIDSGIVER_INFORMASJON.les(PersonDato.serializer(), melding) + + val inntektsmelding = tilInntektsmelding( + aapenId = aapenId, + skjema = skjema, + orgNavn = orgNavn, + sykmeldt = sykmeldt, + avsender = avsender + ) + + logger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'") + sikkerLogger.debug("Skal sende melding med behov 'BehovType.LAGRE_AAPEN_IM'") +// rapid.publish( +// Key.EVENT_NAME to event.toJson(), +// Key.UUID to transaksjonId.toJson(), +// Key.AAPEN_ID to aapenId.toJson(), +// Key.BEHOV to BehovType.LAGRE_AAPEN_IM.toJson(), +// Key.AAPEN_INNTEKTMELDING to inntektsmelding.toJson(Inntektsmelding.serializer()) +// ) + + // TODO Midlertidig sett svar til im-api + val clientId = redisStore.get(RedisKey.of(transaksjonId, event))!!.let(UUID::fromString) + redisStore.set(RedisKey.of(clientId), inntektsmelding.toJsonStr(Inntektsmelding.serializer())) + } + } + } + + override fun finalize(melding: Map) { + val transaksjonId = Key.UUID.les(UuidSerializer, melding) + val aapenId = Key.AAPEN_ID.les(UuidSerializer, melding) + val erDuplikat = Key.ER_DUPLIKAT_IM.les(Boolean.serializer(), melding) + val inntektsmeldingJson = Key.AAPEN_INNTEKTMELDING.les(JsonElement.serializer(), melding) + + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.transaksjonId(transaksjonId), + Log.aapenId(aapenId) + ) { + val clientId = redisStore.get(RedisKey.of(transaksjonId, event))?.let(UUID::fromString) + + if (clientId == null) { + sikkerLogger.error("Forsøkte å fullføre, men clientId mangler i Redis.") + } else { + redisStore.set(RedisKey.of(clientId), inntektsmeldingJson.toString()) + } + + if (!erDuplikat) { + rapid.publish( + Key.EVENT_NAME to EventName.AAPEN_IM_LAGRET.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.AAPEN_INNTEKTMELDING to inntektsmeldingJson + ) + .also { + MdcUtils.withLogFields( + Log.event(EventName.AAPEN_IM_LAGRET) + ) { + logger.info("Publiserte melding.") + sikkerLogger.info("Publiserte melding:\n${it.toPretty()}") + } + } + } + } + } + + override fun onError(melding: Map, fail: Fail) { + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(EventName.AAPEN_IM_MOTTATT), + Log.transaksjonId(fail.transaksjonId) + ) { + val utloesendeBehov = Key.BEHOV.lesOrNull(BehovType.serializer(), fail.utloesendeMelding.toMap()) + val datafeil = when (utloesendeBehov) { + BehovType.VIRKSOMHET -> { + listOf( + Key.VIRKSOMHET to "Ukjent virksomhet".toJson() + ) + } + BehovType.FULLT_NAVN -> { + val sykmeldtFnr = Key.IDENTITETSNUMMER.les(String.serializer(), melding) + val avsenderFnr = Key.ARBEIDSGIVER_ID.les(String.serializer(), melding) + listOf( + Key.ARBEIDSTAKER_INFORMASJON to tomPerson(sykmeldtFnr).toJson(PersonDato.serializer()), + Key.ARBEIDSGIVER_INFORMASJON to tomPerson(avsenderFnr).toJson(PersonDato.serializer()) + ) + } + else -> { + emptyList() + } + } + + if (datafeil.isNotEmpty()) { + datafeil.forEach { + redisStore.set(RedisKey.of(fail.transaksjonId, it.first), it.second.toString()) + } + + val meldingMedDefault = datafeil.toMap() + melding + + return inProgress(meldingMedDefault) + } + + val clientId = redisStore.get(RedisKey.of(fail.transaksjonId, event)) + ?.let(UUID::fromString) + + if (clientId == null) { + val aapenId = Key.AAPEN_ID.lesOrNull(UuidSerializer, fail.utloesendeMelding.toMap()) + sikkerLogger.error("Forsøkte å terminere, men clientId mangler i Redis. aapenId=$aapenId") + } else { + redisStore.set(RedisKey.of(clientId), fail.feilmelding) + } + } + } +} + +private fun tilInntektsmelding( + aapenId: UUID, + skjema: SkjemaInntektsmelding, + orgNavn: String, + sykmeldt: PersonDato, + avsender: PersonDato +): Inntektsmelding = + Inntektsmelding( + id = aapenId, + sykmeldt = Sykmeldt( + fnr = sykmeldt.ident, + navn = sykmeldt.navn + ), + avsender = Avsender( + orgnr = skjema.avsender.orgnr, + orgNavn = orgNavn, + fnr = avsender.ident, + navn = avsender.navn, + tlf = skjema.avsender.tlf + ), + sykmeldingsperioder = skjema.sykmeldingsperioder, + agp = skjema.agp, + inntekt = skjema.inntekt, + refusjon = skjema.refusjon, + aarsakInnsending = skjema.aarsakInnsending, + mottatt = OffsetDateTime.now() + ) + +private fun tomPerson(fnr: String): PersonDato = + PersonDato( + navn = "", + fødselsdato = null, + ident = fnr + ) diff --git a/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/App.kt b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/App.kt new file mode 100644 index 0000000000..02ee3274c2 --- /dev/null +++ b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/App.kt @@ -0,0 +1,23 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice + +import no.nav.helse.rapids_rivers.RapidApplication +import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore +import no.nav.helsearbeidsgiver.utils.log.logger + +private val logger = "im-aapenimservice".logger() + +fun main() { + val redisStore = RedisStore(Env.redisUrl) + + RapidApplication + .create(System.getenv()) + .createAapenImService(redisStore) + .start() +} + +fun RapidsConnection.createAapenImService(redisStore: RedisStore): RapidsConnection = + also { + logger.info("Starter ${AapenImService::class.simpleName}...") + AapenImService(this, redisStore) + } diff --git a/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/Env.kt b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/Env.kt new file mode 100644 index 0000000000..a980cb1884 --- /dev/null +++ b/aapenimservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/aapenimservice/Env.kt @@ -0,0 +1,7 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.aapenimservice + +import no.nav.helsearbeidsgiver.felles.fromEnv + +object Env { + val redisUrl = "REDIS_URL".fromEnv() +} diff --git a/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/TilgangLoeser.kt b/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/TilgangLoeser.kt index edc225c99e..0c9d841b2d 100644 --- a/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/TilgangLoeser.kt +++ b/altinn/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/altinn/TilgangLoeser.kt @@ -24,6 +24,7 @@ import no.nav.helsearbeidsgiver.utils.json.toJson import no.nav.helsearbeidsgiver.utils.log.MdcUtils import java.util.UUID +// TODO test class TilgangLoeser( rapidsConnection: RapidsConnection, private val altinnClient: AltinnClient @@ -40,8 +41,7 @@ class TilgangLoeser( it.interestedIn( Key.UUID, Key.ORGNRUNDERENHET, - Key.FNR, - Key.FORESPOERSEL_ID + Key.FNR ) } } diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt index 862086ef5a..3a8b3f7d05 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/App.kt @@ -16,6 +16,7 @@ import io.ktor.server.routing.route import io.ktor.server.routing.routing import no.nav.helse.rapids_rivers.RapidApplication import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.inntektsmelding.api.aapeninntektmelding.aapenInntektmeldingRoute import no.nav.helsearbeidsgiver.inntektsmelding.api.aktiveorgnr.aktiveOrgnrRoute import no.nav.helsearbeidsgiver.inntektsmelding.api.auth.Tilgangskontroll import no.nav.helsearbeidsgiver.inntektsmelding.api.innsending.innsendingRoute @@ -38,6 +39,7 @@ object Routes { const val TRENGER = "/trenger" const val INNTEKT = "/inntekt" const val INNSENDING = "/inntektsmelding" + const val AAPEN_INNTEKTMELDING = "/aapen-inntektsmelding" const val KVITTERING = "/kvittering" const val AKTIVEORGNR = "/aktiveorgnr" } @@ -100,6 +102,7 @@ fun Application.apiModule(rapid: RapidsConnection) { trengerRoute(rapid, tilgangskontroll, redisPoller) inntektRoute(rapid, tilgangskontroll, redisPoller) innsendingRoute(rapid, tilgangskontroll, redisPoller) + aapenInntektmeldingRoute(rapid, tilgangskontroll, redisPoller) kvitteringRoute(rapid, tilgangskontroll, redisPoller) aktiveOrgnrRoute(rapid, redisPoller) } diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/RedisPoller.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/RedisPoller.kt index 19c6aa21e6..817032c175 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/RedisPoller.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/RedisPoller.kt @@ -35,8 +35,8 @@ class RedisPoller { json.parseJson() } catch (e: Exception) { "JSON-parsing feilet.".let { - sikkerLogger.error("$it key=$key json=$json") - throw RedisPollerJsonParseException("$it Se sikker logg for mer info. key='$key'", e) + sikkerLogger.error("$it key=$key json=$json", e) + throw RedisPollerJsonParseException("$it key='$key'", e) } } } diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingProducer.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingProducer.kt new file mode 100644 index 0000000000..a69067e34b --- /dev/null +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingProducer.kt @@ -0,0 +1,48 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.api.aapeninntektmelding + +import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.inntektsmelding.api.logger +import no.nav.helsearbeidsgiver.inntektsmelding.api.sikkerLogger +import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.json.toPretty +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import java.util.UUID + +// TODO test +class AapenInntektmeldingProducer( + private val rapid: RapidsConnection +) { + init { + logger.info("Starter ${AapenInntektmeldingProducer::class.simpleName}...") + } + + fun publish(aapenId: UUID, avsenderFnr: String, skjema: SkjemaInntektsmelding): UUID { + val clientId = UUID.randomUUID() + + MdcUtils.withLogFields( + Log.event(EventName.AAPEN_IM_MOTTATT), + Log.clientId(clientId), + Log.aapenId(aapenId) + ) { + rapid.publish( + Key.EVENT_NAME to EventName.AAPEN_IM_MOTTATT.toJson(), + Key.CLIENT_ID to clientId.toJson(), + Key.AAPEN_ID to aapenId.toJson(), + Key.SKJEMA_INNTEKTSMELDING to skjema.toJson(SkjemaInntektsmelding.serializer()), + Key.ARBEIDSGIVER_FNR to avsenderFnr.toJson() + ) + .also { + logger.info("Publiserte til kafka.") + sikkerLogger.info("Publiserte til kafka:\n${it.toPretty()}") + } + } + + return clientId + } +} diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingResponse.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingResponse.kt new file mode 100644 index 0000000000..b914644fd2 --- /dev/null +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektmeldingResponse.kt @@ -0,0 +1,13 @@ +@file:UseSerializers(UuidSerializer::class) + +package no.nav.helsearbeidsgiver.inntektsmelding.api.aapeninntektmelding + +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import java.util.UUID + +@Serializable +data class AapenInntektmeldingResponse( + val aapenId: UUID +) diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektsmeldingRoute.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektsmeldingRoute.kt new file mode 100644 index 0000000000..fa086a84a6 --- /dev/null +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/aapeninntektmelding/AapenInntektsmeldingRoute.kt @@ -0,0 +1,124 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.api.aapeninntektmelding + +import io.ktor.http.HttpStatusCode +import io.ktor.server.application.ApplicationCall +import io.ktor.server.application.call +import io.ktor.server.request.receiveText +import io.ktor.server.routing.Route +import io.ktor.server.routing.post +import io.ktor.util.pipeline.PipelineContext +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.json.JsonElement +import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.domene.inntektsmelding.v1.skjema.SkjemaInntektsmelding +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.inntektsmelding.api.RedisPoller +import no.nav.helsearbeidsgiver.inntektsmelding.api.RedisPollerTimeoutException +import no.nav.helsearbeidsgiver.inntektsmelding.api.Routes +import no.nav.helsearbeidsgiver.inntektsmelding.api.auth.Tilgangskontroll +import no.nav.helsearbeidsgiver.inntektsmelding.api.auth.lesFnrFraAuthToken +import no.nav.helsearbeidsgiver.inntektsmelding.api.logger +import no.nav.helsearbeidsgiver.inntektsmelding.api.response.JsonErrorResponse +import no.nav.helsearbeidsgiver.inntektsmelding.api.response.RedisPermanentErrorResponse +import no.nav.helsearbeidsgiver.inntektsmelding.api.response.RedisTimeoutResponse +import no.nav.helsearbeidsgiver.inntektsmelding.api.sikkerLogger +import no.nav.helsearbeidsgiver.inntektsmelding.api.utils.respond +import no.nav.helsearbeidsgiver.inntektsmelding.api.utils.respondBadRequest +import no.nav.helsearbeidsgiver.inntektsmelding.api.utils.respondInternalServerError +import no.nav.helsearbeidsgiver.utils.json.fromJson +import no.nav.helsearbeidsgiver.utils.json.parseJson +import no.nav.helsearbeidsgiver.utils.json.toPretty +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import java.util.UUID + +// TODO test +fun Route.aapenInntektmeldingRoute( + rapid: RapidsConnection, + tilgangskontroll: Tilgangskontroll, + redisPoller: RedisPoller +) { + val producer = AapenInntektmeldingProducer(rapid) + + post(Routes.AAPEN_INNTEKTMELDING) { + val aapenId: UUID = UUID.randomUUID() + + MdcUtils.withLogFields( + Log.apiRoute(Routes.AAPEN_INNTEKTMELDING), + Log.aapenId(aapenId) + ) { + val skjema = lesRequestOrNull() + if (skjema == null) { + respondBadRequest(JsonErrorResponse(inntektsmeldingId = aapenId), JsonErrorResponse.serializer()) + } else if (!skjema.erGyldig()) { + "Fikk valideringsfeil.".also { + logger.info(it) + sikkerLogger.info(it) + } + + // TODO returner (og logg) mer utfyllende feil + respondBadRequest("Valideringsfeil. Mer utfyllende feil må implementeres.", String.serializer()) + } else { + tilgangskontroll.validerTilgangTilOrg(call.request, aapenId, skjema.avsender.orgnr) + + val avsenderFnr = call.request.lesFnrFraAuthToken() + + val clientId = producer.publish(aapenId, avsenderFnr, skjema) + + MdcUtils.withLogFields( + Log.clientId(clientId) + ) { + runCatching { + redisPoller.hent(clientId) + } + .let { + sendResponse(aapenId, it) + } + } + } + } + } +} + +private suspend fun PipelineContext.lesRequestOrNull(): SkjemaInntektsmelding? = + call.receiveText() + .parseJson() + .also { json -> + "Mottok åpen inntektsmelding.".let { + logger.info(it) + sikkerLogger.info("$it:\n${json.toPretty()}") + } + } + .runCatching { + fromJson(SkjemaInntektsmelding.serializer()) + } + .onFailure { e -> + "Kunne ikke parse json.".let { + logger.error(it) + sikkerLogger.error(it, e) + } + } + .getOrNull() + +private suspend fun PipelineContext.sendResponse(aapenId: UUID, result: Result) { + result + .onSuccess { + logger.info("Åpen inntektsmelding mottatt OK.") + sikkerLogger.info("Åpen inntektsmelding mottatt OK:\n${it.toPretty()}") + respond(HttpStatusCode.OK, AapenInntektmeldingResponse(aapenId), AapenInntektmeldingResponse.serializer()) + } + .onFailure { + logger.info("Klarte ikke hente resultat.") + sikkerLogger.info("Klarte ikke hente resultat.", it) + when (it) { + is RedisPollerTimeoutException -> + respondInternalServerError(RedisTimeoutResponse(inntektsmeldingId = aapenId), RedisTimeoutResponse.serializer()) + + else -> + respondInternalServerError(RedisPermanentErrorResponse(aapenId), RedisPermanentErrorResponse.serializer()) + } + } +} + +// TODO +private fun SkjemaInntektsmelding.erGyldig(): Boolean = + true diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/auth/Tilgangskontroll.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/auth/Tilgangskontroll.kt index f1adfd6605..106e158ba2 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/auth/Tilgangskontroll.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/auth/Tilgangskontroll.kt @@ -16,17 +16,37 @@ class Tilgangskontroll( private val cache: LocalCache, private val redisPoller: RedisPoller ) { - fun validerTilgang( + fun validerTilgangTilForespoersel( request: ApplicationRequest, - id: UUID + forespoerselId: UUID + ) { + validerTilgang(request, forespoerselId) { fnr -> + tilgangProducer.publishForespoerselId(forespoerselId, fnr) + } + } + + fun validerTilgangTilOrg( + request: ApplicationRequest, + id: UUID, + orgnr: String + ) { + validerTilgang(request, id) { fnr -> + tilgangProducer.publishOrgnr(orgnr, fnr) + } + } + + private fun validerTilgang( + request: ApplicationRequest, + id: UUID, + publish: (String) -> UUID ) { val innloggerFnr = request.lesFnrFraAuthToken() val tilgang = runBlocking { cache.get("$innloggerFnr:$id") { - logger.info("Fant ikke forespørsel i cache, ber om tilgangskontroll for '$id'.") + logger.info("Fant ikke tilgang i cache, ber om tilgangskontroll for '$id'.") - val clientId = tilgangProducer.publish(id, innloggerFnr) + val clientId = publish(innloggerFnr) val resultat = redisPoller.hent(clientId) .fromJson(TilgangData.serializer()) diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/innsending/InnsendingRoute.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/innsending/InnsendingRoute.kt index defc32143d..24777504c2 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/innsending/InnsendingRoute.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/innsending/InnsendingRoute.kt @@ -103,8 +103,9 @@ fun Route.innsendingRoute( } } - tilgangskontroll.validerTilgang(call.request, forespoerselId) + tilgangskontroll.validerTilgangTilForespoersel(call.request, forespoerselId) + // TODO sjekk gyldighet mot forespørsel, f. eks. forespurtData matcher request.validate() val innloggerFnr = call.request.lesFnrFraAuthToken() val clientId = producer.publish(forespoerselId, request, innloggerFnr) diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/inntekt/InntektRoute.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/inntekt/InntektRoute.kt index 651d07ca06..84aa808b89 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/inntekt/InntektRoute.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/inntekt/InntektRoute.kt @@ -37,7 +37,7 @@ fun Route.inntektRoute( post { val request = call.receive() - tilgangskontroll.validerTilgang(call.request, request.forespoerselId) + tilgangskontroll.validerTilgangTilForespoersel(call.request, request.forespoerselId) "Henter oppdatert inntekt for forespørselId: ${request.forespoerselId}".let { logger.info(it) diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt index 44aae05af0..709dc69bb7 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/kvittering/KvitteringRoute.kt @@ -68,7 +68,7 @@ fun Route.kvitteringRoute( measureTimeMillis { try { measureTimeMillis { - tilgangskontroll.validerTilgang(call.request, forespoerselId) + tilgangskontroll.validerTilgangTilForespoersel(call.request, forespoerselId) }.also { logger.info("Authorize took $it") } diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/JsonErrorResponse.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/JsonErrorResponse.kt index 231af8f8f0..0bdb1bd777 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/JsonErrorResponse.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/JsonErrorResponse.kt @@ -1,10 +1,21 @@ +@file:UseSerializers(UuidSerializer::class) + package no.nav.helsearbeidsgiver.inntektsmelding.api.response +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import java.util.UUID @Serializable +@OptIn(ExperimentalSerializationApi::class) data class JsonErrorResponse( - val forespoerselId: String + // TODO slett etter endring i frontend + val forespoerselId: String? = null, + val inntektsmeldingId: UUID? = null ) { + @EncodeDefault val error = "Feil under serialisering." } diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/RedisTimeoutResponse.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/RedisTimeoutResponse.kt index b9ce2c52a2..3d30d6ed1b 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/RedisTimeoutResponse.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/response/RedisTimeoutResponse.kt @@ -2,14 +2,29 @@ package no.nav.helsearbeidsgiver.inntektsmelding.api.response +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer import java.util.UUID @Serializable +@OptIn(ExperimentalSerializationApi::class) data class RedisTimeoutResponse( - val uuid: UUID + // TODO slett etter endring i frontend + val uuid: UUID? = null, + val inntektsmeldingId: UUID? = null ) { + @EncodeDefault val error = "Brukte for lang tid mot redis." } + +@Serializable +@OptIn(ExperimentalSerializationApi::class) +data class RedisPermanentErrorResponse( + val inntektsmeldingId: UUID +) { + @EncodeDefault + val error = "Permanent feil mot redis." +} diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/tilgang/TilgangProducer.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/tilgang/TilgangProducer.kt index ed8919d8df..860ae5ee0b 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/tilgang/TilgangProducer.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/tilgang/TilgangProducer.kt @@ -1,5 +1,6 @@ package no.nav.helsearbeidsgiver.inntektsmelding.api.tilgang +import kotlinx.serialization.json.JsonElement import no.nav.helse.rapids_rivers.RapidsConnection import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key @@ -21,20 +22,32 @@ class TilgangProducer( logger.info("Starter ${TilgangProducer::class.simpleName}...") } - fun publish(forespoerselId: UUID, fnr: String): UUID { + fun publishForespoerselId(forespoerselId: UUID, fnr: String): UUID = + publish( + EventName.TILGANG_FORESPOERSEL_REQUESTED, + Key.FORESPOERSEL_ID to forespoerselId.toJson(), + Key.FNR to fnr.toJson() + ) + + fun publishOrgnr(orgnr: String, fnr: String): UUID = + publish( + EventName.TILGANG_ORG_REQUESTED, + Key.ORGNRUNDERENHET to orgnr.toJson(), + Key.FNR to fnr.toJson() + ) + + private fun publish(eventName: EventName, vararg messageFields: Pair): UUID { val clientId = randomUuid() MdcUtils.withLogFields( Log.klasse(this), - Log.event(EventName.TILGANG_REQUESTED), - Log.clientId(clientId), - Log.forespoerselId(forespoerselId) + Log.event(eventName), + Log.clientId(clientId) ) { rapid.publish( - Key.EVENT_NAME to EventName.TILGANG_REQUESTED.toJson(), + Key.EVENT_NAME to eventName.toJson(), Key.CLIENT_ID to clientId.toJson(), - Key.FORESPOERSEL_ID to forespoerselId.toJson(), - Key.FNR to fnr.toJson() + *messageFields ) .also { json -> "Publiserte request om tilgang.".let { diff --git a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRoute.kt b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRoute.kt index 185257e50d..e00fbf943d 100644 --- a/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRoute.kt +++ b/api/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRoute.kt @@ -47,7 +47,7 @@ fun Route.trengerRoute( .onSuccess { request -> logger.info("Henter data for uuid: ${request.uuid}") try { - tilgangskontroll.validerTilgang(call.request, request.uuid) + tilgangskontroll.validerTilgangTilForespoersel(call.request, request.uuid) val arbeidsgiverFnr = call.request.lesFnrFraAuthToken() diff --git a/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRouteKtTest.kt b/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRouteKtTest.kt index 1f6c08ba3f..51f6aecd23 100644 --- a/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRouteKtTest.kt +++ b/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/trenger/TrengerRouteKtTest.kt @@ -109,7 +109,7 @@ class TrengerRouteKtTest : ApiTest() { fun `skal returnere Forbidden hvis feil i Tilgangsresultet`() = testApi { val mockTilgangClientId = UUID.randomUUID() - every { anyConstructed().publish(any(), any()) } returns mockTilgangClientId + every { anyConstructed().publishForespoerselId(any(), any()) } returns mockTilgangClientId coEvery { anyConstructed().hent(mockTilgangClientId) } returns TilgangData( feil = FeilReport( diff --git a/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/utils/TestUtils.kt b/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/utils/TestUtils.kt index 1c4757a7a3..d9add0e284 100644 --- a/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/utils/TestUtils.kt +++ b/api/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/api/utils/TestUtils.kt @@ -64,7 +64,7 @@ class TestClient( fun mockTilgang(tilgang: Tilgang) { val mockTilgangClientId = UUID.randomUUID() - every { anyConstructed().publish(any(), any()) } returns mockTilgangClientId + every { anyConstructed().publishForespoerselId(any(), any()) } returns mockTilgangClientId coEvery { anyConstructed().hent(mockTilgangClientId) } returns TilgangData(tilgang).toJson(TilgangData.serializer()) } diff --git a/brreg/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/brreg/VirksomhetLoeser.kt b/brreg/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/brreg/VirksomhetLoeser.kt index 8121c3a85f..37d3bbcdd0 100644 --- a/brreg/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/brreg/VirksomhetLoeser.kt +++ b/brreg/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/brreg/VirksomhetLoeser.kt @@ -106,6 +106,7 @@ class VirksomhetLoeser( eventName = behov.event, transaksjonId = transaksjonId, forespoerselId = behov.forespoerselId?.let(UUID::fromString), + Key.AAPEN_ID to json[Key.AAPEN_ID], Key.VIRKSOMHET to navnListe.values.first().toJson(), Key.VIRKSOMHETER to navnListe.toJson() ) diff --git a/config/aapenimservice/dev-gcp.yml b/config/aapenimservice/dev-gcp.yml new file mode 100644 index 0000000000..47b7d8d766 --- /dev/null +++ b/config/aapenimservice/dev-gcp.yml @@ -0,0 +1,6 @@ +kafkaPool: nav-dev +env: +- name: REDIS_URL + value: redis://helsearbeidsgiver-redis.helsearbeidsgiver.svc.cluster.local:6379/0 +apps: + - name: helsearbeidsgiver-redis diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt index 11fe4afc7d..43b666394d 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/EventTypes.kt @@ -31,13 +31,17 @@ enum class BehovType { @Serializable enum class EventName { - TILGANG_REQUESTED, + TILGANG_FORESPOERSEL_REQUESTED, + TILGANG_ORG_REQUESTED, KVITTERING_REQUESTED, TRENGER_REQUESTED, INNTEKT_REQUESTED, INSENDING_STARTED, AKTIVE_ORGNR_REQUESTED, + AAPEN_IM_MOTTATT, + AAPEN_IM_LAGRET, + EKSTERN_INNTEKTSMELDING_REQUESTED, EKSTERN_INNTEKTSMELDING_MOTTATT, EKSTERN_INNTEKTSMELDING_LAGRET, diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/Key.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/Key.kt index e842906fec..02bc2bdb38 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/Key.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/Key.kt @@ -14,6 +14,7 @@ enum class Key(override val str: String) : IKey { BEHOV("@behov"), // Egendefinerte + AAPEN_ID("aapen_id"), IDENTITETSNUMMER("identitetsnummer"), ARBEIDSGIVER_ID("arbeidsgiverId"), UUID("uuid"), @@ -22,6 +23,8 @@ enum class Key(override val str: String) : IKey { JOURNALPOST_ID("journalpostId"), DATA("data"), FAIL("fail"), + SKJEMA_INNTEKTSMELDING("skjema_inntektsmelding"), + AAPEN_INNTEKTMELDING("aapen_inntektmelding"), // Tidligere DataFelt VIRKSOMHET("virksomhet"), diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/Loeser.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/Loeser.kt index 3a99cf5821..0d490b9f32 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/Loeser.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/Loeser.kt @@ -14,8 +14,10 @@ import no.nav.helsearbeidsgiver.felles.json.toMap import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Behov import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail.Companion.publish +import no.nav.helsearbeidsgiver.felles.utils.Log import no.nav.helsearbeidsgiver.utils.json.parseJson import no.nav.helsearbeidsgiver.utils.json.toPretty +import no.nav.helsearbeidsgiver.utils.log.MdcUtils import no.nav.helsearbeidsgiver.utils.log.logger import no.nav.helsearbeidsgiver.utils.log.sikkerLogger @@ -46,29 +48,31 @@ abstract class Loeser(val rapidsConnection: RapidsConnection) : River.PacketList } override fun onPacket(packet: JsonMessage, context: MessageContext) { - val json = packet.toJson().parseJson().toMap() + val melding = packet.toJson().parseJson().toMap() - logger.info("Mottok melding med behov '${json[Key.BEHOV]}'.") - sikkerLogger.info("Mottok melding:\n${packet.toPretty()}") + val eventName = Key.EVENT_NAME.les(EventName.serializer(), melding) + val behovType = Key.BEHOV.les(BehovType.serializer(), melding) + val forespoerselId = Key.FORESPOERSEL_ID.lesOrNull(String.serializer(), melding) - val forespoerselId = Key.FORESPOERSEL_ID.lesOrNull(String.serializer(), json) + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(eventName), + Log.behov(behovType) + ) { + logger.info("Mottok melding med behov '$behovType'.") + sikkerLogger.info("Mottok melding:\n${packet.toPretty()}") - if (forespoerselId == null) { - logger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er 'null'.") - sikkerLogger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er 'null'.") - } else if (forespoerselId.isEmpty()) { - logger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er en tom streng.") - sikkerLogger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er en tom streng.") + if (forespoerselId == null) { + logger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er 'null'.") + sikkerLogger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er 'null'.") + } else if (forespoerselId.isEmpty()) { + logger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er en tom streng.") + sikkerLogger.warn("Mangler forespørselId! '${Key.FORESPOERSEL_ID}' er en tom streng.") + } } - if (!packet[Key.BEHOV.str].isArray) { - val behov = Behov( - Key.EVENT_NAME.les(EventName.serializer(), json), - Key.BEHOV.les(BehovType.serializer(), json), - forespoerselId?.takeIf { it.isNotEmpty() }, - packet - ) - onBehov(behov) - } + val behov = Behov(eventName, behovType, forespoerselId, packet) + + onBehov(behov) } } diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/model/Behov.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/model/Behov.kt index a664475cc3..c1437bf089 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/model/Behov.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/rapidsrivers/model/Behov.kt @@ -46,6 +46,7 @@ class Behov( it.rejectKey(Key.FAIL.str) it.interestedIn(Key.UUID.str) it.interestedIn(Key.FORESPOERSEL_ID.str) + it.interestedIn(Key.AAPEN_ID.str) } } diff --git a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/utils/Log.kt b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/utils/Log.kt index 4c67959569..aa85a0e65a 100644 --- a/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/utils/Log.kt +++ b/felles/src/main/kotlin/no/nav/helsearbeidsgiver/felles/utils/Log.kt @@ -20,9 +20,13 @@ object Log { fun forespoerselId(value: UUID) = "forespoersel_id" to value.toString() + fun aapenId(value: UUID) = "aapen_id" to value.toString() + fun sakId(value: String) = "sak_id" to value fun oppgaveId(value: String) = "oppgave_id" to value + fun apiRoute(value: String) = "api_route" to value + fun ukjentType(value: String) = "ukjent_type" to value } diff --git a/gradle.properties b/gradle.properties index 766685e792..97f341d3c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ kotlinVersion=1.9.21 kotlinterVersion=3.13.0 # Dependency versions -hagDomeneInntektsmeldingVersion=0.0.12 +hagDomeneInntektsmeldingVersion=0.0.13 junitJupiterVersion=5.10.1 kotestVersion=5.8.0 kotlinCoroutinesVersion=1.7.3 diff --git a/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/TilgangskontrollIT.kt b/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/TilgangskontrollIT.kt index f57fc7d277..1aac931b07 100644 --- a/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/TilgangskontrollIT.kt +++ b/integrasjonstest/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/integrasjonstest/TilgangskontrollIT.kt @@ -3,7 +3,6 @@ package no.nav.helsearbeidsgiver.inntektsmelding.integrasjonstest import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import io.mockk.coEvery -import kotlinx.serialization.builtins.serializer import no.nav.helsearbeidsgiver.felles.EventName import no.nav.helsearbeidsgiver.felles.Key import no.nav.helsearbeidsgiver.felles.Tilgang @@ -37,12 +36,12 @@ class TilgangskontrollIT : EndToEndTest() { } @Test - fun `skal få tilgang`() { - tilgangProducer.publish(Mock.forespoerselIdMedTilgang, Mock.INNLOGGET_FNR) + fun `forespoersel - skal få tilgang`() { + tilgangProducer.publishForespoerselId(Mock.forespoerselIdMedTilgang, Mock.INNLOGGET_FNR) Thread.sleep(6000) - val result = messages.filter(EventName.TILGANG_REQUESTED) + val result = messages.filter(EventName.TILGANG_FORESPOERSEL_REQUESTED) .filter(Key.TILGANG) .firstAsMap() @@ -54,12 +53,12 @@ class TilgangskontrollIT : EndToEndTest() { } @Test - fun `skal bli nektet tilgang`() { - tilgangProducer.publish(Mock.forespoerselIdUtenTilgang, Mock.INNLOGGET_FNR) + fun `forespoersel - skal bli nektet tilgang`() { + tilgangProducer.publishForespoerselId(Mock.forespoerselIdUtenTilgang, Mock.INNLOGGET_FNR) Thread.sleep(4000) - val result = messages.filter(EventName.TILGANG_REQUESTED) + val result = messages.filter(EventName.TILGANG_FORESPOERSEL_REQUESTED) .filter(Key.TILGANG) .firstAsMap() @@ -71,12 +70,12 @@ class TilgangskontrollIT : EndToEndTest() { } @Test - fun `skal få melding om at forespørsel ikke finnes`() { - tilgangProducer.publish(Mock.forespoerselIdFinnesIkke, Mock.INNLOGGET_FNR) + fun `forespoersel - skal få melding om at forespørsel ikke finnes`() { + tilgangProducer.publishForespoerselId(Mock.forespoerselIdFinnesIkke, Mock.INNLOGGET_FNR) Thread.sleep(4000) - val fail = messages.filter(EventName.TILGANG_REQUESTED) + val fail = messages.filter(EventName.TILGANG_FORESPOERSEL_REQUESTED) .filterFeil() .firstAsMap() .get(Key.FAIL) @@ -86,6 +85,40 @@ class TilgangskontrollIT : EndToEndTest() { fail.feilmelding shouldBe "Fant ingen orgnr for forespørsel-ID '${Mock.forespoerselIdFinnesIkke}'." } + @Test + fun `organisasjon - skal få tilgang`() { + tilgangProducer.publishOrgnr(Mock.ORGNR_MED_TILGANG, Mock.INNLOGGET_FNR) + + Thread.sleep(6000) + + val result = messages.filter(EventName.TILGANG_ORG_REQUESTED) + .filter(Key.TILGANG) + .firstAsMap() + + val tilgang = result[Key.TILGANG] + .shouldNotBeNull() + .fromJson(Tilgang.serializer()) + + tilgang shouldBe Tilgang.HAR_TILGANG + } + + @Test + fun `organisasjon - skal bli nektet tilgang`() { + tilgangProducer.publishOrgnr(Mock.ORGNR_UTEN_TILGANG, Mock.INNLOGGET_FNR) + + Thread.sleep(4000) + + val result = messages.filter(EventName.TILGANG_ORG_REQUESTED) + .filter(Key.TILGANG) + .firstAsMap() + + val tilgang = result[Key.TILGANG] + .shouldNotBeNull() + .fromJson(Tilgang.serializer()) + + tilgang shouldBe Tilgang.IKKE_TILGANG + } + private object Mock { const val INNLOGGET_FNR = "10436700000" diff --git a/pdl/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/pdl/FulltNavnLoeser.kt b/pdl/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/pdl/FulltNavnLoeser.kt index 263831a3a6..b0510c3339 100644 --- a/pdl/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/pdl/FulltNavnLoeser.kt +++ b/pdl/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/pdl/FulltNavnLoeser.kt @@ -77,6 +77,7 @@ class FulltNavnLoeser( eventName = behov.event, transaksjonId = transaksjonId, forespoerselId = behov.forespoerselId?.let(UUID::fromString), + Key.AAPEN_ID to json[Key.AAPEN_ID], Key.ARBEIDSTAKER_INFORMASJON to arbeidstakerInfo.toJson(PersonDato.serializer()), Key.ARBEIDSGIVER_INFORMASJON to arbeidsgiverInfo.toJson(PersonDato.serializer()) ) diff --git a/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/App.kt b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/App.kt index 52bffadc4c..670c87d125 100644 --- a/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/App.kt +++ b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/App.kt @@ -16,6 +16,9 @@ fun main() { fun RapidsConnection.createTilgangService(redisStore: RedisStore): RapidsConnection = also { - logger.info("Starter ${TilgangService::class.simpleName}...") - TilgangService(this, redisStore) + logger.info("Starter ${TilgangForespoerselService::class.simpleName}...") + TilgangForespoerselService(this, redisStore) + + logger.info("Starter ${TilgangOrgService::class.simpleName}...") + TilgangOrgService(this, redisStore) } diff --git a/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangService.kt b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangForespoerselService.kt similarity index 86% rename from tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangService.kt rename to tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangForespoerselService.kt index 4f2a8651ba..de475241df 100644 --- a/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangService.kt +++ b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangForespoerselService.kt @@ -31,7 +31,7 @@ import no.nav.helsearbeidsgiver.utils.log.logger import no.nav.helsearbeidsgiver.utils.log.sikkerLogger import java.util.UUID -class TilgangService( +class TilgangForespoerselService( private val rapid: RapidsConnection, override val redisStore: RedisStore ) : CompositeEventListener() { @@ -39,7 +39,7 @@ class TilgangService( private val logger = logger() private val sikkerLogger = sikkerLogger() - override val event = EventName.TILGANG_REQUESTED + override val event = EventName.TILGANG_FORESPOERSEL_REQUESTED override val startKeys = listOf( Key.FORESPOERSEL_ID, Key.FNR @@ -60,14 +60,16 @@ class TilgangService( val forespoerselId = Key.FORESPOERSEL_ID.les(UuidSerializer, melding) MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), Log.transaksjonId(transaksjonId), Log.forespoerselId(forespoerselId) ) { rapid.publish( Key.EVENT_NAME to event.toJson(), Key.BEHOV to BehovType.HENT_IM_ORGNR.toJson(), - Key.FORESPOERSEL_ID to forespoerselId.toJson(), - Key.UUID to transaksjonId.toJson() + Key.UUID to transaksjonId.toJson(), + Key.FORESPOERSEL_ID to forespoerselId.toJson() ) .also { MdcUtils.withLogFields( @@ -84,6 +86,8 @@ class TilgangService( val forespoerselId = Key.FORESPOERSEL_ID.les(UuidSerializer, melding) MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), Log.transaksjonId(transaksjonId), Log.forespoerselId(forespoerselId) ) { @@ -104,10 +108,10 @@ class TilgangService( rapid.publish( Key.EVENT_NAME to event.toJson(), Key.BEHOV to BehovType.TILGANGSKONTROLL.toJson(), + Key.UUID to transaksjonId.toJson(), Key.FORESPOERSEL_ID to forespoerselId.toJson(), Key.ORGNRUNDERENHET to orgnr.toJson(), - Key.FNR to fnr.toJson(), - Key.UUID to transaksjonId.toJson() + Key.FNR to fnr.toJson() ) .also { MdcUtils.withLogFields( @@ -131,21 +135,22 @@ class TilgangService( if (clientId == null) { sikkerLogger.error("Kunne ikke lese clientId for $transaksjonId fra Redis") } else { - val tilgang = RedisKey.of(transaksjonId, Key.TILGANG).read() - val feil = RedisKey.of(transaksjonId, Feilmelding("")).read() - - val tilgangJson = TilgangData( - tilgang = tilgang?.fromJson(Tilgang.serializer()), - feil = feil?.fromJson(FeilReport.serializer()) - ) - .toJson(TilgangData.serializer()) - - RedisKey.of(clientId).write(tilgangJson) - MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), Log.clientId(clientId), Log.transaksjonId(transaksjonId) ) { + val tilgang = RedisKey.of(transaksjonId, Key.TILGANG).read() + val feil = RedisKey.of(transaksjonId, Feilmelding("")).read() + + val tilgangJson = TilgangData( + tilgang = tilgang?.fromJson(Tilgang.serializer()), + feil = feil?.fromJson(FeilReport.serializer()) + ) + .toJson(TilgangData.serializer()) + + RedisKey.of(clientId).write(tilgangJson) sikkerLogger.info("$event fullført.") } } @@ -182,6 +187,8 @@ class TilgangService( RedisKey.of(clientId).write(feilReport.toJson(FeilReport.serializer())) MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), Log.clientId(clientId), Log.transaksjonId(fail.transaksjonId) ) { diff --git a/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangOrgService.kt b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangOrgService.kt new file mode 100644 index 0000000000..8834d27c70 --- /dev/null +++ b/tilgangservice/src/main/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/tilgangservice/TilgangOrgService.kt @@ -0,0 +1,163 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.tilgangservice + +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.json.JsonElement +import no.nav.helse.rapids_rivers.RapidsConnection +import no.nav.helsearbeidsgiver.felles.BehovType +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.FeilReport +import no.nav.helsearbeidsgiver.felles.Feilmelding +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.Tilgang +import no.nav.helsearbeidsgiver.felles.TilgangData +import no.nav.helsearbeidsgiver.felles.json.les +import no.nav.helsearbeidsgiver.felles.json.lesOrNull +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.json.toMap +import no.nav.helsearbeidsgiver.felles.rapidsrivers.FailKanal +import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullDataKanal +import no.nav.helsearbeidsgiver.felles.rapidsrivers.StatefullEventListener +import no.nav.helsearbeidsgiver.felles.rapidsrivers.composite.CompositeEventListener +import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail +import no.nav.helsearbeidsgiver.felles.rapidsrivers.publish +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisStore +import no.nav.helsearbeidsgiver.felles.utils.Log +import no.nav.helsearbeidsgiver.utils.json.fromJson +import no.nav.helsearbeidsgiver.utils.json.serializer.UuidSerializer +import no.nav.helsearbeidsgiver.utils.json.toJson +import no.nav.helsearbeidsgiver.utils.json.toPretty +import no.nav.helsearbeidsgiver.utils.log.MdcUtils +import no.nav.helsearbeidsgiver.utils.log.logger +import no.nav.helsearbeidsgiver.utils.log.sikkerLogger +import java.util.UUID + +class TilgangOrgService( + private val rapid: RapidsConnection, + override val redisStore: RedisStore +) : CompositeEventListener() { + + private val logger = logger() + private val sikkerLogger = sikkerLogger() + + override val event = EventName.TILGANG_ORG_REQUESTED + override val startKeys = listOf( + Key.ORGNRUNDERENHET, + Key.FNR + ) + override val dataKeys = listOf( + Key.TILGANG + ) + + init { + StatefullEventListener(rapid, event, redisStore, startKeys, ::onPacket) + StatefullDataKanal(rapid, event, redisStore, dataKeys, ::onPacket) + FailKanal(rapid, event, ::onPacket) + } + + override fun new(melding: Map) { + val transaksjonId = Key.UUID.les(UuidSerializer, melding) + val orgnr = Key.ORGNRUNDERENHET.les(String.serializer(), melding) + val fnr = Key.FNR.les(String.serializer(), melding) + + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.transaksjonId(transaksjonId) + ) { + rapid.publish( + Key.EVENT_NAME to event.toJson(), + Key.BEHOV to BehovType.TILGANGSKONTROLL.toJson(), + Key.UUID to transaksjonId.toJson(), + Key.ORGNRUNDERENHET to orgnr.toJson(), + Key.FNR to fnr.toJson() + ) + .also { + MdcUtils.withLogFields( + Log.behov(BehovType.TILGANGSKONTROLL) + ) { + sikkerLogger.info("Publiserte melding:\n${it.toPretty()}.") + } + } + } + } + + override fun inProgress(melding: Map) { + "Service skal aldri være \"underveis\".".also { + logger.error(it) + sikkerLogger.error(it) + } + } + + override fun finalize(melding: Map) { + val transaksjonId = Key.UUID.les(UuidSerializer, melding) + + val clientId = RedisKey.of(transaksjonId, event) + .read()?.let(UUID::fromString) + + if (clientId == null) { + sikkerLogger.error("Kunne ikke lese clientId for $transaksjonId fra Redis") + } else { + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.clientId(clientId), + Log.transaksjonId(transaksjonId) + ) { + val tilgang = RedisKey.of(transaksjonId, Key.TILGANG).read() + val feil = RedisKey.of(transaksjonId, Feilmelding("")).read() + + val tilgangJson = TilgangData( + tilgang = tilgang?.fromJson(Tilgang.serializer()), + feil = feil?.fromJson(FeilReport.serializer()) + ) + .toJson(TilgangData.serializer()) + + RedisKey.of(clientId).write(tilgangJson) + sikkerLogger.info("$event fullført.") + } + } + } + + override fun onError(melding: Map, fail: Fail) { + val utloesendeBehov = Key.BEHOV.lesOrNull(BehovType.serializer(), fail.utloesendeMelding.toMap()) + + val feilReport = if (utloesendeBehov == BehovType.TILGANGSKONTROLL) { + val feilmelding = Feilmelding("Teknisk feil, prøv igjen senere.", -1, Key.TILGANG) + + sikkerLogger.error("Returnerer feilmelding: '${feilmelding.melding}'") + + FeilReport( + mutableListOf(feilmelding) + ) + } else { + FeilReport() + } + + val clientId = RedisKey.of(fail.transaksjonId, event) + .read() + ?.let(UUID::fromString) + + if (clientId == null) { + sikkerLogger.error("$event forsøkt terminert, kunne ikke finne ${fail.transaksjonId} i redis!") + } else { + RedisKey.of(clientId).write(feilReport.toJson(FeilReport.serializer())) + + MdcUtils.withLogFields( + Log.klasse(this), + Log.event(event), + Log.clientId(clientId), + Log.transaksjonId(fail.transaksjonId) + ) { + sikkerLogger.error("$event terminert.") + } + } + } + + private fun RedisKey.write(json: JsonElement) { + redisStore.set(this, json.toString()) + } + + private fun RedisKey.read(): String? = + redisStore.get(this) +} diff --git a/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangServiceTest.kt b/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangForespoerselServiceTest.kt similarity index 82% rename from tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangServiceTest.kt rename to tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangForespoerselServiceTest.kt index 41e4b8e7e7..560eeabf89 100644 --- a/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangServiceTest.kt +++ b/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangForespoerselServiceTest.kt @@ -15,18 +15,18 @@ import no.nav.helsearbeidsgiver.felles.json.toJson import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey import no.nav.helsearbeidsgiver.felles.test.mock.MockRedis -import no.nav.helsearbeidsgiver.inntektsmelding.tilgangservice.TilgangService +import no.nav.helsearbeidsgiver.inntektsmelding.tilgangservice.TilgangForespoerselService import no.nav.helsearbeidsgiver.utils.json.toJsonStr import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import java.util.UUID -class TilgangServiceTest { +class TilgangForespoerselServiceTest { private val testRapid = TestRapid() private val mockRedis = MockRedis() - private val service = TilgangService(testRapid, mockRedis.store) + private val service = TilgangForespoerselService(testRapid, mockRedis.store) @BeforeEach fun setup() { @@ -37,12 +37,7 @@ class TilgangServiceTest { @Test fun `kritisk feil stopper flyten`() { - // TODO: uuid *må* være satt i Fail - ellers kastes IllegalStateException ved onError() - // Kunne endret dette til å returnere Transaction.TERMINATE, men da gjenoppstår - // problemet som en IllegalArgumentException i .terminate() - // Kanskje bør uuid enforces til ikke-null i Fail? - - val event = EventName.TILGANG_REQUESTED + val event = EventName.TILGANG_FORESPOERSEL_REQUESTED val clientId = UUID.randomUUID() val transaksjonId = UUID.randomUUID() diff --git a/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangOrgServiceTest.kt b/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangOrgServiceTest.kt new file mode 100644 index 0000000000..b4ac2dfa0a --- /dev/null +++ b/tilgangservice/src/test/kotlin/no/nav/helsearbeidsgiver/inntektsmelding/inntektservice/TilgangOrgServiceTest.kt @@ -0,0 +1,73 @@ +package no.nav.helsearbeidsgiver.inntektsmelding.inntektservice + +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.verify +import kotlinx.serialization.json.JsonObject +import no.nav.helse.rapids_rivers.testsupport.TestRapid +import no.nav.helsearbeidsgiver.felles.BehovType +import no.nav.helsearbeidsgiver.felles.EventName +import no.nav.helsearbeidsgiver.felles.FeilReport +import no.nav.helsearbeidsgiver.felles.Feilmelding +import no.nav.helsearbeidsgiver.felles.Key +import no.nav.helsearbeidsgiver.felles.json.toJson +import no.nav.helsearbeidsgiver.felles.rapidsrivers.model.Fail +import no.nav.helsearbeidsgiver.felles.rapidsrivers.redis.RedisKey +import no.nav.helsearbeidsgiver.felles.test.mock.MockRedis +import no.nav.helsearbeidsgiver.inntektsmelding.tilgangservice.TilgangOrgService +import no.nav.helsearbeidsgiver.utils.json.toJsonStr +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import java.util.UUID + +class TilgangOrgServiceTest { + + private val testRapid = TestRapid() + private val mockRedis = MockRedis() + + private val service = TilgangOrgService(testRapid, mockRedis.store) + + @BeforeEach + fun setup() { + testRapid.reset() + clearAllMocks() + mockRedis.setup() + } + + @Test + fun `kritisk feil stopper flyten`() { + val event = EventName.TILGANG_ORG_REQUESTED + val clientId = UUID.randomUUID() + val transaksjonId = UUID.randomUUID() + + every { mockRedis.store.get(RedisKey.of(transaksjonId, event)) } returns clientId.toString() + + val fail = Fail( + feilmelding = "ikkeno", + event = event, + transaksjonId = transaksjonId, + forespoerselId = null, + utloesendeMelding = JsonObject( + mapOf( + Key.BEHOV.str to BehovType.TILGANGSKONTROLL.toJson() + ) + ) + ) + + shouldNotThrowAny { + service.onError(emptyMap(), fail) + } + + val expectedFeilReport = FeilReport( + mutableListOf( + Feilmelding("Teknisk feil, prøv igjen senere.", -1, Key.TILGANG) + ) + ) + .toJsonStr(FeilReport.serializer()) + + verify { + mockRedis.store.set(RedisKey.of(clientId), expectedFeilReport) + } + } +}