diff --git a/.github/workflows/api-start-stopp.yml b/.github/workflows/api-start-stopp.yml index 38e8c4f2..9e1dc2b6 100644 --- a/.github/workflows/api-start-stopp.yml +++ b/.github/workflows/api-start-stopp.yml @@ -1,11 +1,10 @@ name: Api Start stopp on: push: - branches: - - main paths: - 'apps/api-start-stopp-perioder/**' - - 'lib/kafka-key-generator-client/**' + - 'domain/**' + - 'lib/**' - '.github/workflows/api-start-stopp.yml' - 'gradle/**' - 'settings.gradle.kts' diff --git a/.github/workflows/hendelselogg-backup.yaml b/.github/workflows/hendelselogg-backup.yaml index 74c42e42..362f503a 100644 --- a/.github/workflows/hendelselogg-backup.yaml +++ b/.github/workflows/hendelselogg-backup.yaml @@ -4,8 +4,8 @@ on: push: paths: - 'apps/hendelselogg-backup/**' - - 'lib/kafka/**' - - 'lib/hoplite-config/**' + - 'lib/**' + - 'domain/**' - '.github/workflows/hendelselogg-backup.yaml' - 'gradle/**' - 'settings.gradle.kts' diff --git a/.github/workflows/hendelseprosessor.yaml b/.github/workflows/hendelseprosessor.yaml index cbac2c2e..745d10e8 100644 --- a/.github/workflows/hendelseprosessor.yaml +++ b/.github/workflows/hendelseprosessor.yaml @@ -2,11 +2,10 @@ name: Hendelseprosessor on: push: - branches: - - main paths: - 'apps/hendelseprosessor/**' - - 'lib/kafka-key-generator-client/**' + - 'lib/**' + - 'domain/**' - '.github/workflows/hendelseprosessor.yaml' - 'gradle/**' - 'settings.gradle.kts' diff --git a/.github/workflows/utgang-formidlingsgruppe-deploy.yaml b/.github/workflows/utgang-formidlingsgruppe-deploy.yaml index 9f553104..5156f901 100644 --- a/.github/workflows/utgang-formidlingsgruppe-deploy.yaml +++ b/.github/workflows/utgang-formidlingsgruppe-deploy.yaml @@ -2,12 +2,10 @@ name: Formidlingsgruppe - Utgang on: push: - branches: - - main paths: - 'apps/utgang-formidlingsgruppe/**' - - 'lib/kafka-key-generator-client/**' - - 'domain/main-avro-schema/**' + - 'lib/**' + - 'domain/**' - '.github/workflows/utgang-formidlingsgruppe-deploy.yaml' - 'gradle/**' - 'settings.gradle.kts' diff --git a/.github/workflows/utgang-pdl-deploy.yaml b/.github/workflows/utgang-pdl-deploy.yaml index 2549a427..bbb245da 100644 --- a/.github/workflows/utgang-pdl-deploy.yaml +++ b/.github/workflows/utgang-pdl-deploy.yaml @@ -2,13 +2,11 @@ name: PDL - Utgang on: push: - branches: - - main paths: - 'apps/utgang-pdl/**' - '.github/workflows/utgang-pdl-deploy.yaml' - - 'lib/kafka-key-generator-client/**' - - 'domain/main-avro-schema-classes/**' + - 'lib/**' + - 'domain/**' - 'gradle/**' - 'settings.gradle.kts' - 'gradle.properties' diff --git a/apps/api-start-stopp-perioder/build.gradle.kts b/apps/api-start-stopp-perioder/build.gradle.kts index 1a15e289..1d09653d 100644 --- a/apps/api-start-stopp-perioder/build.gradle.kts +++ b/apps/api-start-stopp-perioder/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(project(":lib:kafka")) implementation(project(":lib:hoplite-config")) implementation(project(":lib:kafka-key-generator-client")) + implementation(project(":domain:arbeidssoeker-regler")) implementation(hoplite.hopliteCore) implementation(hoplite.hopliteToml) implementation(hoplite.hopliteYaml) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/AuthOpplysningerTilHendelseOpplysniinger.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/AuthOpplysningerTilHendelseOpplysniinger.kt new file mode 100644 index 00000000..d8d26852 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/AuthOpplysningerTilHendelseOpplysniinger.kt @@ -0,0 +1,15 @@ +package no.nav.paw.arbeidssokerregisteret + +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.* +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.* +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning + +fun authOpplysningTilHendelseOpplysning(opplysning: AuthOpplysning): Opplysning = + when (opplysning) { + IkkeSammeSomInnloggerBruker -> Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER + SammeSomInnloggetBruker -> Opplysning.SAMME_SOM_INNLOGGET_BRUKER + TokenXPidIkkeFunnet -> Opplysning.TOKENX_PID_IKKE_FUNNET + AnsattIkkeTilgang -> Opplysning.ANSATT_IKKE_TILGANG + AnsattTilgang -> Opplysning.ANSATT_TILGANG + IkkeAnsatt -> Opplysning.IKKE_ANSATT + } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Opplysning.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Opplysning.kt deleted file mode 100644 index 13cd765b..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Opplysning.kt +++ /dev/null @@ -1,72 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application - -enum class Opplysning(val beskrivelse: String) { - FORHAANDSGODKJENT_AV_ANSATT("Registrering er forhåndsgodkjent av NAV-ansatt"), - SAMME_SOM_INNLOGGET_BRUKER("Start/stopp av periode er på samme bruker som er innlogget"), - IKKE_SAMME_SOM_INNLOGGER_BRUKER("Start/stopp av periode er ikke på samme bruker som er innlogget"), - ANSATT_IKKE_TILGANG("Innlogget bruker er en NAV-ansatt uten tilgang til bruker som start/stopp av periode utføres på"), - ANSATT_TILGANG("Innlogget bruker er en NAV-ansatt med tilgang til bruker som start/stopp av periode utføres på"), - IKKE_ANSATT("Innlogget bruker er ikke en NAV-ansatt"), - ER_OVER_18_AAR("Personen start/stopp av periode utføres på er over 18 år"), - ER_UNDER_18_AAR("Personen start/stopp av periode utføres på er under 18 år"), - UKJENT_FOEDSELSDATO("Personen start/stopp av periode utføres på har ukjent fødselsdato"), - UKJENT_FOEDSELSAAR("Personen start/stopp av periode utføres på har ukjent fødselsår"), - TOKENX_PID_IKKE_FUNNET("Innlogget bruker er ikke en logget inn via TOKENX med PID(dvs ikke sluttbruker via ID-Porten)"), - OPPHOERT_IDENTITET("Personen start/stopp av periode utføres på har opphørt identitet(annulert i Folkeregisteret)"), - IKKE_BOSATT("Personen start/stopp av periode utføres på er ikke bosatt i Norge(eventuelt er innlytting anullert)"), - DOED("Personen start/stopp av periode utføres på er død"), - SAVNET("Personen start/stopp av periode utføres på er savnet"), - HAR_NORSK_ADRESSE("Personen start/stopp av periode utføres på har norsk adresse"), - HAR_UTENLANDSK_ADRESSE("Personen start/stopp av periode utføres på har utenlandsk adresse"), - INGEN_ADRESSE_FUNNET("Personen start/stopp av periode utføres på har ingen adresse i våre systemer"), - BOSATT_ETTER_FREG_LOVEN("Personen start/stopp av periode utføres på er bosatt i Norge i henhold til Folkeregisterloven"), - DNUMMER("Personen start/stopp av periode utføres på har D-nummer"), - UKJENT_FORENKLET_FREG_STATUS("Personen start/stopp av periode utføres på har ukjent forenklet folkeregisterstatus"), - HAR_GYLDIG_OPPHOLDSTILLATELSE("Personen start/stopp av periode utføres på har gyldig oppholdstillatelse"), - OPPHOLDSTILATELSE_UTGAATT("Personen start/stopp av periode utføres på har oppholdstillatelse som er utgått"), - BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE("Personen start/stopp av periode utføres på er født i Norge uten oppholdstillatelse"), - INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE("Personen start/stopp av periode utføres på har ingen informasjon om oppholdstillatelse"), - UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE("Personen start/stopp av periode utføres på har ukjent status for oppholdstillatelse"), - PERSON_IKKE_FUNNET("Personen start/stopp av periode utføres på er ikke funnet i våre systemer"), - SISTE_FLYTTING_VAR_UT_AV_NORGE("Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste var ut av Norge"), - SISTE_FLYTTING_VAR_INN_TIL_NORGE("Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste var inn til Norge"), - IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING("Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste ikke er mulig å identifisere"), - INGEN_FLYTTE_INFORMASJON("Personen start/stopp av periode utføres på har ingen flytte informasjon"), -} - -operator fun Opplysning.plus(opplysning: Opplysning): Set = setOf(this, opplysning) - -fun mapToHendelseOpplysning(opplysning: Opplysning): no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning = - when (opplysning) { - Opplysning.FORHAANDSGODKJENT_AV_ANSATT -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.FORHAANDSGODKJENT_AV_ANSATT - Opplysning.SAMME_SOM_INNLOGGET_BRUKER -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.SAMME_SOM_INNLOGGET_BRUKER - Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER - Opplysning.ANSATT_IKKE_TILGANG -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.ANSATT_IKKE_TILGANG - Opplysning.ANSATT_TILGANG -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.ANSATT_TILGANG - Opplysning.IKKE_ANSATT -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.IKKE_ANSATT - Opplysning.ER_OVER_18_AAR -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.ER_OVER_18_AAR - Opplysning.ER_UNDER_18_AAR -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.ER_UNDER_18_AAR - Opplysning.UKJENT_FOEDSELSDATO -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.UKJENT_FOEDSELSDATO - Opplysning.UKJENT_FOEDSELSAAR -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.UKJENT_FOEDSELSAAR - Opplysning.TOKENX_PID_IKKE_FUNNET -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.TOKENX_PID_IKKE_FUNNET - Opplysning.OPPHOERT_IDENTITET -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.OPPHOERT_IDENTITET - Opplysning.IKKE_BOSATT -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.IKKE_BOSATT - Opplysning.DOED -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.DOED - Opplysning.SAVNET -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.SAVNET - Opplysning.HAR_NORSK_ADRESSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.HAR_NORSK_ADRESSE - Opplysning.HAR_UTENLANDSK_ADRESSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.HAR_UTENLANDSK_ADRESSE - Opplysning.INGEN_ADRESSE_FUNNET -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.INGEN_ADRESSE_FUNNET - Opplysning.BOSATT_ETTER_FREG_LOVEN -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.BOSATT_ETTER_FREG_LOVEN - Opplysning.DNUMMER -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.DNUMMER - Opplysning.UKJENT_FORENKLET_FREG_STATUS -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.UKJENT_FORENKLET_FREG_STATUS - Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE - Opplysning.OPPHOLDSTILATELSE_UTGAATT -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.OPPHOLDSTILATELSE_UTGAATT - Opplysning.BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE - Opplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE - Opplysning.UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE - Opplysning.PERSON_IKKE_FUNNET -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.PERSON_IKKE_FUNNET - Opplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE - Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE - Opplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING - Opplysning.INGEN_FLYTTE_INFORMASJON -> no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.INGEN_FLYTTE_INFORMASJON - } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/OpplysningerRequestHandler.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/OpplysningerRequestHandler.kt index 1c9d670d..a32a0861 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/OpplysningerRequestHandler.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/OpplysningerRequestHandler.kt @@ -1,12 +1,12 @@ package no.nav.paw.arbeidssokerregisteret.application +import arrow.core.Either +import arrow.core.raise.either +import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Feil import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.OpplysningerRequest import no.nav.paw.arbeidssokerregisteret.RequestScope import no.nav.paw.arbeidssokerregisteret.api.extensions.getId -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationErrorResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResultOk -import no.nav.paw.arbeidssokerregisteret.domain.http.validerOpplysninger +import no.nav.paw.arbeidssokerregisteret.domain.http.validering.validerOpplysninger import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse import no.nav.paw.config.kafka.sendDeferred import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient @@ -23,30 +23,31 @@ class OpplysningerRequestHandler( private val logger = LoggerFactory.getLogger(this::class.java) context(RequestScope) - suspend fun opprettBrukeropplysninger(opplysningerRequest: OpplysningerRequest): Either { - val identitetsnummer = opplysningerRequest.getId() - - val validerTilgangResultat = requestValidator.validerTilgang(identitetsnummer) - - if (validerTilgangResultat is IkkeTilgang) { - return Left(validerTilgangResultat) - } - - val validerOpplysninger = validerOpplysninger(opplysningerRequest.opplysningerOmArbeidssoeker) - - if (validerOpplysninger is ValidationErrorResult) { - return Right(validerOpplysninger) + suspend fun opprettBrukeropplysninger(opplysningerRequest: OpplysningerRequest): Either = + either { + val identitetsnummer = opplysningerRequest.getId() + requestValidator.validerTilgang(identitetsnummer) + .mapLeft { problem -> + Feil( + melding = problem.regel.beskrivelse, + feilKode = Feil.FeilKode.IKKE_TILGANG + ) + }.bind() + validerOpplysninger(opplysningerRequest.opplysningerOmArbeidssoeker) + .mapLeft { validationErrorResult -> + Feil( + melding = validationErrorResult.message, + feilKode = Feil.FeilKode.FEIL_VED_LESING_AV_FORESPORSEL + ) + }.bind() + val (id, key) = kafkaKeysClient.getIdAndKey(identitetsnummer.verdi) + val hendelse = opplysningerHendelse(id, opplysningerRequest) + val record = ProducerRecord( + hendelseTopic, + key, + hendelse + ) + val recordMetadata = producer.sendDeferred(record).await() + logger.trace("Sendte melding til kafka: type={}, offset={}", hendelse.hendelseType, recordMetadata.offset()) } - val (id, key) = kafkaKeysClient.getIdAndKey(identitetsnummer.verdi) - - val hendelse = opplysningerHendelse(id, opplysningerRequest) - val record = ProducerRecord( - hendelseTopic, - key, - hendelse - ) - val recordMetadata = producer.sendDeferred(record).await() - logger.trace("Sendte melding til kafka: type={}, offset={}", hendelse.hendelseType, recordMetadata.offset()) - return Right(ValidationResultOk) - } } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt deleted file mode 100644 index d9f6aa0b..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt +++ /dev/null @@ -1,37 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application - -data class Regel( - val id: RegelId, - /** - * Beskrivelse av regelen - */ - val beskrivelse: String, - /** - * Opplysninger som må være tilstede for at regelen skal være sann - */ - val opplysninger: List, - - private val vedTreff: (Regel, Iterable) -> A -) { - fun vedTreff(opplysning: Iterable): A = vedTreff(this, opplysning) -} - - - -operator fun String.invoke( - vararg opplysninger: Opplysning, - id: RegelId, - vedTreff: (Regel, Iterable) -> A -) = Regel( - id = id, - beskrivelse = this, - vedTreff = vedTreff, - opplysninger = opplysninger.toList() -) - -fun Regel.evaluer(samletOpplysning: Iterable): Boolean = opplysninger.all { samletOpplysning.contains(it) } - -fun List>.evaluer(opplysninger: Iterable): A = - filter { regel -> regel.evaluer(opplysninger) } - .map { regel -> regel.vedTreff(opplysninger) } - .first() diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt deleted file mode 100644 index 104fac4b..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt +++ /dev/null @@ -1,39 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application - -enum class RegelId { - IKKE_FUNNET, - SAVNET, - DOED, - ENDRE_FOR_ANNEN_BRUKER, - ANSATT_IKKE_TILGANG_TIL_BRUKER, - IKKE_TILGANG, - UNDER_18_AAR, - IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN, - FORHAANDSGODKJENT_AV_ANSATT, - OVER_18_AAR_OG_BOSATT_ETTER_FREG_LOVEN, - ANSATT_HAR_TILGANG_TIL_BRUKER, - ENDRE_EGEN_BRUKER, - UKJENT_ALDER, - IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT; - - val eksternRegelId: EksternRegelId? - get() = try { - EksternRegelId.valueOf(name) - } catch (e: IllegalArgumentException) { - null - } -} - -enum class EksternRegelId { - UKJENT_REGEL, - IKKE_FUNNET, - SAVNET, - DOED, - ENDRE_FOR_ANNEN_BRUKER, - ANSATT_IKKE_TILGANG_TIL_BRUKER, - IKKE_TILGANG, - UNDER_18_AAR, - IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN, - UKJENT_ALDER, - IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidator.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidator.kt index 0d64fc2b..96c9b5b5 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidator.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidator.kt @@ -1,9 +1,12 @@ package no.nav.paw.arbeidssokerregisteret.application +import arrow.core.Either +import arrow.core.flatMap import io.opentelemetry.instrumentation.annotations.WithSpan import no.nav.paw.arbeidssokerregisteret.RequestScope -import no.nav.paw.arbeidssokerregisteret.application.fakta.* -import no.nav.paw.arbeidssokerregisteret.application.regler.reglerForInngangIPrioritertRekkefolge +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.navAnsattTilgangFakta +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.tokenXPidFakta +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.* import no.nav.paw.arbeidssokerregisteret.application.regler.tilgangsReglerIPrioritertRekkefolge import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService @@ -17,41 +20,47 @@ class RequestValidator( context(RequestScope) @WithSpan - fun validerTilgang(identitetsnummer: Identitetsnummer, erForhaandsGodkjentAvVeileder: Boolean = false): TilgangskontrollResultat { + fun validerTilgang( + identitetsnummer: Identitetsnummer, + erForhaandsGodkjentAvVeileder: Boolean = false + ): Either { val autentiseringsFakta = tokenXPidFakta(identitetsnummer) + - autorisasjonService.navAnsattTilgangFakta(identitetsnummer) + - if (erForhaandsGodkjentAvVeileder) { - setOf(Opplysning.FORHAANDSGODKJENT_AV_ANSATT) - } else { - emptySet() - } + autorisasjonService.navAnsattTilgangFakta(identitetsnummer) + + if (erForhaandsGodkjentAvVeileder) { + setOf(DomeneOpplysning.ErForhaandsgodkjent) + } else { + emptySet() + } return tilgangsReglerIPrioritertRekkefolge.evaluer(autentiseringsFakta) } context(RequestScope) @WithSpan - suspend fun validerStartAvPeriodeOenske(identitetsnummer: Identitetsnummer, erForhaandsGodkjentAvVeileder: Boolean = false): EndeligResultat { - val tilgangsResultat = validerTilgang(identitetsnummer, erForhaandsGodkjentAvVeileder) - if (tilgangsResultat is EndeligResultat) { - return tilgangsResultat - } else { - val person = personInfoService.hentPersonInfo(identitetsnummer.verdi) - val opplysning = person?.let { genererPersonFakta(it) } ?: setOf(Opplysning.PERSON_IKKE_FUNNET) - return reglerForInngangIPrioritertRekkefolge.evaluer(opplysning + tilgangsResultat.opplysning) - } - } -} + suspend fun validerStartAvPeriodeOenske( + identitetsnummer: Identitetsnummer, + erForhaandsGodkjentAvVeileder: Boolean = false + ): Either = + validerTilgang(identitetsnummer, erForhaandsGodkjentAvVeileder) + .flatMap { tilgangsResultat -> + val person = personInfoService.hentPersonInfo(identitetsnummer.verdi) + val opplysning = person?.let { genererPersonFakta(it) } ?: setOf(DomeneOpplysning.PersonIkkeFunnet) + reglerForInngangIPrioritertRekkefolge.evaluer(opplysning + tilgangsResultat.opplysning) + } + -fun genererPersonFakta(person: Person): Set { - require(person.foedsel.size <= 1) { "Personen har flere fødselsdatoer enn forventet" } - require(person.bostedsadresse.size <= 1) { "Personen har flere bostedsadresser enn forventet" } - require(person.opphold.size <= 1) { "Personen har flere opphold enn forventet" } + fun genererPersonFakta(person: Person): Set { + require(person.foedsel.size <= 1) { "Personen har flere fødselsdatoer enn forventet" } + require(person.bostedsadresse.size <= 1) { "Personen har flere bostedsadresser enn forventet" } + require(person.opphold.size <= 1) { "Personen har flere opphold enn forventet" } - return alderFakta(person.foedsel.firstOrNull()) + - adresseFakta(person.bostedsadresse.firstOrNull()) + - forenkletFregFakta(person.folkeregisterpersonstatus) + - oppholdstillatelseFakta(person.opphold.firstOrNull()) + - utflyttingFakta(person.innflyttingTilNorge , person.utflyttingFraNorge) + return alderOpplysning(person.foedsel.firstOrNull()) + + adreseOpplysning(person.bostedsadresse.firstOrNull()) + + euEoesStatsborgerOpplysning(person.statsborgerskap) + + gbrStatsborgerOpplysning(person.statsborgerskap) + + forenkletFregOpplysning(person.folkeregisterpersonstatus) + + oppholdstillatelseOpplysning(person.opphold.firstOrNull()) + + utflyttingOpplysning(person.innflyttingTilNorge, person.utflyttingFraNorge) + } } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt deleted file mode 100644 index 9f1623ec..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt +++ /dev/null @@ -1,167 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application - -import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.OpplysningerRequest -import no.nav.paw.arbeidssokerregisteret.ApplicationInfo -import no.nav.paw.arbeidssokerregisteret.RequestScope -import no.nav.paw.arbeidssokerregisteret.api.extensions.toInternalApi -import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer -import no.nav.paw.arbeidssokerregisteret.domain.navAnsatt -import no.nav.paw.arbeidssokerregisteret.intern.v1.* -import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker -import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType -import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.OpplysningerOmArbeidssoeker -import no.nav.paw.arbeidssokerregisteret.utils.TokenXPID -import java.time.Instant -import java.util.* -import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist as AvvistHendelse -import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata as HendelseMetadata - -sealed interface Resultat { - val opplysning: Iterable - val regel: Regel -} - -sealed interface EndeligResultat : Resultat -sealed interface TilgangskontrollResultat : Resultat - -data class OK( - override val regel: Regel, - override val opplysning: Iterable -) : EndeligResultat - -data class Avvist( - override val regel: Regel, - override val opplysning: Iterable -) : EndeligResultat - -data class Uavklart( - override val regel: Regel, - override val opplysning: Iterable -) : EndeligResultat - -data class IkkeTilgang( - override val regel: Regel, - override val opplysning: Iterable -) : EndeligResultat, TilgangskontrollResultat - -data class TilgangOK( - override val regel: Regel, - override val opplysning: Iterable -) : TilgangskontrollResultat - -data class UgyldigRequestBasertPaaAutentisering( - override val regel: Regel, - override val opplysning: Iterable -) : EndeligResultat, TilgangskontrollResultat - -context(RequestScope) -fun stoppResultatSomHendelse(id: Long, identitetsnummer: Identitetsnummer, resultat: TilgangskontrollResultat): Hendelse = - when (resultat) { - is IkkeTilgang -> AvvistStoppAvPeriode( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat) - ) - - is TilgangOK -> Avsluttet( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat) - ) - - is UgyldigRequestBasertPaaAutentisering -> AvvistStoppAvPeriode( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat) - ) - } - -context(RequestScope) -fun somHendelse(id: Long, identitetsnummer: Identitetsnummer, resultat: EndeligResultat): Hendelse = - when (resultat) { - is Avvist -> AvvistHendelse( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat), - opplysninger = resultat.opplysning.map(::mapToHendelseOpplysning).toSet(), - handling = path - ) - - is IkkeTilgang -> AvvistHendelse( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat) - ) - - is OK -> Startet( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat), - opplysninger = resultat.opplysning.map(::mapToHendelseOpplysning).toSet() - ) - - is Uavklart -> AvvistHendelse( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat), - opplysninger = resultat.opplysning.map(::mapToHendelseOpplysning).toSet() - ) - - is UgyldigRequestBasertPaaAutentisering -> AvvistHendelse( - id = id, - hendelseId = UUID.randomUUID(), - identitetsnummer = identitetsnummer.verdi, - metadata = hendelseMetadata(resultat), - opplysninger = resultat.opplysning.map(::mapToHendelseOpplysning).toSet() - ) - } - -context(RequestScope) -fun opplysningerHendelse(id: Long, opplysningerRequest: OpplysningerRequest): Hendelse = OpplysningerOmArbeidssoekerMottatt( - hendelseId = UUID.randomUUID(), - id = id, - identitetsnummer = opplysningerRequest.identitetsnummer, - opplysningerOmArbeidssoeker = OpplysningerOmArbeidssoeker( - id = UUID.randomUUID(), - metadata = HendelseMetadata( - tidspunkt = Instant.now(), - utfoertAv = brukerFraClaims(), - kilde = "paw-arbeidssoekerregisteret-inngang", - aarsak = "opplysning om arbeidssøker sendt inn" - ), - annet = opplysningerRequest.opplysningerOmArbeidssoeker.annet.toInternalApi(), - helse = opplysningerRequest.opplysningerOmArbeidssoeker.helse.toInternalApi(), - jobbsituasjon = opplysningerRequest.opplysningerOmArbeidssoeker.jobbsituasjon.toInternalApi(), - utdanning = opplysningerRequest.opplysningerOmArbeidssoeker.utdanning.toInternalApi() - ) -) - -context(RequestScope) -fun hendelseMetadata(resultat: Resultat): HendelseMetadata = HendelseMetadata( - tidspunkt = Instant.now(), - utfoertAv = brukerFraClaims(), - kilde = ApplicationInfo.id, - aarsak = resultat.regel.beskrivelse -) - -context(RequestScope) -fun brukerFraClaims(): Bruker { - return claims[TokenXPID]?.let { foedselsnummer -> - Bruker( - type = BrukerType.SLUTTBRUKER, - id = foedselsnummer.verdi - ) - } ?: navAnsatt(claims)?.let { navAnsatt -> - Bruker( - type = BrukerType.VEILEDER, - id = navAnsatt.ident - ) - } ?: throw IllegalStateException("Kunne ikke finne bruker i claims") -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ResultatTilHendelse.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ResultatTilHendelse.kt new file mode 100644 index 00000000..96b0cc42 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ResultatTilHendelse.kt @@ -0,0 +1,111 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import arrow.core.Either +import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.OpplysningerRequest +import no.nav.paw.arbeidssokerregisteret.ApplicationInfo +import no.nav.paw.arbeidssokerregisteret.RequestScope +import no.nav.paw.arbeidssokerregisteret.api.extensions.toInternalApi +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning +import no.nav.paw.arbeidssokerregisteret.authOpplysningTilHendelseOpplysning +import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer +import no.nav.paw.arbeidssokerregisteret.domain.navAnsatt +import no.nav.paw.arbeidssokerregisteret.intern.v1.* +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.* +import no.nav.paw.arbeidssokerregisteret.utils.TokenXPID +import java.time.Instant +import java.util.* +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning as HendelseOpplysning + + +context(RequestScope) +fun stoppResultatSomHendelse(id: Long, identitetsnummer: Identitetsnummer, resultat: Either): Hendelse = + when (resultat) { + is Either.Left -> AvvistStoppAvPeriode( + id = id, + hendelseId = UUID.randomUUID(), + identitetsnummer = identitetsnummer.verdi, + metadata = hendelseMetadata(resultat.value.regel.beskrivelse), + opplysninger = resultat.value.opplysning.map(::mapToHendelseOpplysning).toSet() + ) + + is Either.Right -> Avsluttet( + id = id, + hendelseId = UUID.randomUUID(), + identitetsnummer = identitetsnummer.verdi, + metadata = hendelseMetadata("Stopp av periode"), + opplysninger = resultat.value.opplysning.map(::mapToHendelseOpplysning).toSet(), + ) + } + +fun mapToHendelseOpplysning(opplysning: Opplysning): HendelseOpplysning = + when (opplysning) { + is AuthOpplysning -> authOpplysningTilHendelseOpplysning(opplysning) + is DomeneOpplysning -> domeneOpplysningTilHendelseOpplysning(opplysning) + else -> HendelseOpplysning.UKJENT_OPPLYSNING + } + +context(RequestScope) +fun somHendelse(id: Long, identitetsnummer: Identitetsnummer, resultat: Either): Hendelse = + when (resultat) { + is Either.Left -> Avvist( + id = id, + hendelseId = UUID.randomUUID(), + identitetsnummer = identitetsnummer.verdi, + metadata = hendelseMetadata(resultat.value.regel.beskrivelse), + opplysninger = resultat.value.opplysning.map(::mapToHendelseOpplysning).toSet(), + handling = path + ) + + is Either.Right -> Startet( + id = id, + hendelseId = UUID.randomUUID(), + identitetsnummer = identitetsnummer.verdi, + metadata = hendelseMetadata(resultat.value.regel.beskrivelse), + opplysninger = resultat.value.opplysning.map(::mapToHendelseOpplysning).toSet() + ) + } + +context(RequestScope) +fun opplysningerHendelse(id: Long, opplysningerRequest: OpplysningerRequest): Hendelse = OpplysningerOmArbeidssoekerMottatt( + hendelseId = UUID.randomUUID(), + id = id, + identitetsnummer = opplysningerRequest.identitetsnummer, + opplysningerOmArbeidssoeker = OpplysningerOmArbeidssoeker( + id = UUID.randomUUID(), + metadata = Metadata( + tidspunkt = Instant.now(), + utfoertAv = brukerFraClaims(), + kilde = ApplicationInfo.id, + aarsak = "opplysning om arbeidssøker sendt inn" + ), + annet = opplysningerRequest.opplysningerOmArbeidssoeker.annet.toInternalApi(), + helse = opplysningerRequest.opplysningerOmArbeidssoeker.helse.toInternalApi(), + jobbsituasjon = opplysningerRequest.opplysningerOmArbeidssoeker.jobbsituasjon.toInternalApi(), + utdanning = opplysningerRequest.opplysningerOmArbeidssoeker.utdanning.toInternalApi() + ) +) + +context(RequestScope) +fun hendelseMetadata(aarsak: String): Metadata = Metadata( + tidspunkt = Instant.now(), + utfoertAv = brukerFraClaims(), + kilde = ApplicationInfo.id, + aarsak = aarsak +) + +context(RequestScope) +fun brukerFraClaims(): Bruker { + return claims[TokenXPID]?.let { foedselsnummer -> + Bruker( + type = BrukerType.SLUTTBRUKER, + id = foedselsnummer.verdi + ) + } ?: navAnsatt(claims)?.let { navAnsatt -> + Bruker( + type = BrukerType.VEILEDER, + id = navAnsatt.ident + ) + } ?: throw IllegalStateException("Kunne ikke finne bruker i claims") +} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ReturKoder.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ReturKoder.kt deleted file mode 100644 index f8394639..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/ReturKoder.kt +++ /dev/null @@ -1,14 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application - -const val MIDLERTIDIG_INTERNT_RESULTAT = -1 - -const val GODTATT = 0 -const val AVVIST_PERSON_IKKE_FUNNET = 50 -const val AVVIST_ALDER = 51 -const val AVVIST_IKKE_BOSATT_I_NORGE_IHT_FOLKEREGISTERLOVEN = 52 - -const val AVVIST_UAVKLART = 100 - -const val IKKE_TILGANG = 150 -const val IKKE_TILGANG_ANNEN_BRUKER = 151 -const val IKKE_TILGANG_ANSATT_IKKE_TILGANG_TIL_BRUKER = 152 diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/StartStoppRequestHandler.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/StartStoppRequestHandler.kt index 7248c14d..8fe3cf02 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/StartStoppRequestHandler.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/StartStoppRequestHandler.kt @@ -1,5 +1,6 @@ package no.nav.paw.arbeidssokerregisteret.application +import arrow.core.Either import io.opentelemetry.instrumentation.annotations.WithSpan import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope @@ -10,8 +11,6 @@ import no.nav.paw.config.kafka.sendDeferred import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient import org.apache.kafka.clients.producer.Producer import org.apache.kafka.clients.producer.ProducerRecord -import org.apache.kafka.clients.producer.internals.BuiltInPartitioner.partitionForKey -import org.apache.kafka.common.serialization.LongSerializer import org.slf4j.LoggerFactory class StartStoppRequestHandler( @@ -22,17 +21,9 @@ class StartStoppRequestHandler( ) { private val logger = LoggerFactory.getLogger(this::class.java) - private fun calculatePartition(recordKey: Long): Int? { - return if (hendelseTopic == "paw.arbeidssoker-hendelseslogg-beta-v9") { - partitionForKey(LongSerializer().serialize(hendelseTopic, recordKey), 6) - } else { - null - } - } - context(RequestScope) @WithSpan - suspend fun startArbeidssokerperiode(identitetsnummer: Identitetsnummer, erForhaandsGodkjentAvVeileder: Boolean): EndeligResultat = + suspend fun startArbeidssokerperiode(identitetsnummer: Identitetsnummer, erForhaandsGodkjentAvVeileder: Boolean): Either = coroutineScope { val kafkaKeysResponse = async { kafkaKeysClient.getIdAndKey(identitetsnummer.verdi) } val resultat = requestValidator.validerStartAvPeriodeOenske(identitetsnummer, erForhaandsGodkjentAvVeileder) @@ -49,7 +40,7 @@ class StartStoppRequestHandler( context(RequestScope) @WithSpan - suspend fun avsluttArbeidssokerperiode(identitetsnummer: Identitetsnummer): TilgangskontrollResultat { + suspend fun avsluttArbeidssokerperiode(identitetsnummer: Identitetsnummer): Either { val (id, key) = kafkaKeysClient.getIdAndKey(identitetsnummer.verdi) val tilgangskontrollResultat = requestValidator.validerTilgang(identitetsnummer) val hendelse = stoppResultatSomHendelse(id, identitetsnummer, tilgangskontrollResultat) @@ -64,10 +55,10 @@ class StartStoppRequestHandler( } context(RequestScope) - suspend fun kanRegistreresSomArbeidssoker(identitetsnummer: Identitetsnummer): EndeligResultat { + suspend fun kanRegistreresSomArbeidssoker(identitetsnummer: Identitetsnummer): Either { val (id, key) = kafkaKeysClient.getIdAndKey(identitetsnummer.verdi) val resultat = requestValidator.validerStartAvPeriodeOenske(identitetsnummer) - if (resultat !is OK) { + if (resultat.isLeft()) { val hendelse = somHendelse(id, identitetsnummer, resultat) val record = ProducerRecord( hendelseTopic, @@ -80,8 +71,3 @@ class StartStoppRequestHandler( return resultat } } - - -sealed interface Either -data class Left(val value: L) : Either -data class Right(val value: R) : Either diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/AuthOpplysninger.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/AuthOpplysninger.kt new file mode 100644 index 00000000..fbbf78de --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/AuthOpplysninger.kt @@ -0,0 +1,40 @@ +package no.nav.paw.arbeidssokerregisteret.application.authfaktka + +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning + + +sealed interface AuthOpplysning: Opplysning { + + data object IkkeSammeSomInnloggerBruker : AuthOpplysning { + override val id = "IKKE_SAMME_SOM_INNLOGGER_BRUKER" + override val beskrivelse = "Start/stopp av periode er ikke på samme bruker som er innlogget" + } + + data object SammeSomInnloggetBruker : AuthOpplysning { + override val id = "SAMME_SOM_INNLOGGET_BRUKER" + override val beskrivelse = "Start/stopp av periode er på samme bruker som er innlogget" + } + + data object TokenXPidIkkeFunnet : AuthOpplysning { + override val id = "TOKENX_PID_IKKE_FUNNET" + override val beskrivelse = + "Innlogget bruker er ikke en logget inn via TOKENX med PID(dvs ikke sluttbruker via ID-Porten)" + } + + data object AnsattIkkeTilgang : AuthOpplysning { + override val id = "ANSATT_IKKE_TILGANG" + override val beskrivelse = + "Innlogget bruker er en NAV-ansatt uten tilgang til bruker som start/stopp av periode utføres på" + } + + data object AnsattTilgang : AuthOpplysning { + override val id = "ANSATT_TILGANG" + override val beskrivelse = + "Innlogget bruker er en NAV-ansatt med tilgang til bruker som start/stopp av periode utføres på" + } + + data object IkkeAnsatt : AuthOpplysning { + override val id = "IKKE_ANSATT" + override val beskrivelse = "Innlogget bruker er ikke en NAV-ansatt" + } +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/NavAnsattTilgangFakta.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/NavAnsattTilgangFakta.kt similarity index 69% rename from apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/NavAnsattTilgangFakta.kt rename to apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/NavAnsattTilgangFakta.kt index 6e8458cd..dfc0d796 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/NavAnsattTilgangFakta.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/NavAnsattTilgangFakta.kt @@ -1,8 +1,9 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta +package no.nav.paw.arbeidssokerregisteret.application.authfaktka import io.opentelemetry.api.trace.Span import no.nav.paw.arbeidssokerregisteret.RequestScope -import no.nav.paw.arbeidssokerregisteret.application.Opplysning +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.* +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer import no.nav.paw.arbeidssokerregisteret.domain.navAnsatt import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService @@ -12,13 +13,12 @@ fun AutorisasjonService.navAnsattTilgangFakta(identitetsnummer: Identitetsnummer val navAnsatt = navAnsatt(claims) return (if (navAnsatt != null) { if (verifiserVeilederTilgangTilBruker(navAnsatt, identitetsnummer)) { - Opplysning.ANSATT_TILGANG + AnsattTilgang } else { - Opplysning.ANSATT_IKKE_TILGANG + AnsattIkkeTilgang } - } - else { - Opplysning.IKKE_ANSATT + } else { + IkkeAnsatt }).also { opplysning -> Span.current() .setAttribute("paw_nav_ansatt_tilgang", opplysning.toString()) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/TokenXPidFakta.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/TokenXPidFakta.kt similarity index 61% rename from apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/TokenXPidFakta.kt rename to apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/TokenXPidFakta.kt index ea91577d..dae0600e 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/TokenXPidFakta.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/authfaktka/TokenXPidFakta.kt @@ -1,8 +1,9 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta +package no.nav.paw.arbeidssokerregisteret.application.authfaktka import io.opentelemetry.api.trace.Span import no.nav.paw.arbeidssokerregisteret.RequestScope -import no.nav.paw.arbeidssokerregisteret.application.Opplysning +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.* +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer import no.nav.paw.arbeidssokerregisteret.utils.TokenXPID @@ -10,13 +11,14 @@ context(RequestScope) fun tokenXPidFakta(identitetsnummer: Identitetsnummer): Opplysning { return (claims[TokenXPID]?.let { authenticatedUser -> if (authenticatedUser != identitetsnummer) { - Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER + IkkeSammeSomInnloggerBruker } else { - Opplysning.SAMME_SOM_INNLOGGET_BRUKER + AuthOpplysning.SammeSomInnloggetBruker } - } ?: Opplysning.TOKENX_PID_IKKE_FUNNET) + } ?: AuthOpplysning.TokenXPidIkkeFunnet) .also { opplysning -> Span.current() .setAttribute("paw_tokenx_pid", opplysning.toString()) } } + diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AddresseFakta.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AddresseFakta.kt deleted file mode 100644 index b7701381..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AddresseFakta.kt +++ /dev/null @@ -1,15 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta - -import no.nav.paw.arbeidssokerregisteret.application.Opplysning -import no.nav.paw.pdl.graphql.generated.hentperson.Bostedsadresse - -fun adresseFakta(adresse: Bostedsadresse?): Opplysning { - return when { - adresse == null -> Opplysning.INGEN_ADRESSE_FUNNET - adresse.vegadresse?.kommunenummer != null -> Opplysning.HAR_NORSK_ADRESSE - adresse.matrikkeladresse?.kommunenummer != null -> Opplysning.HAR_NORSK_ADRESSE - adresse.ukjentBosted?.bostedskommune != null -> Opplysning.HAR_NORSK_ADRESSE - adresse.utenlandskAdresse != null -> Opplysning.HAR_UTENLANDSK_ADRESSE - else -> Opplysning.INGEN_ADRESSE_FUNNET - } -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/ForenkletFRegFakta.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/ForenkletFRegFakta.kt deleted file mode 100644 index ebdc91f9..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/ForenkletFRegFakta.kt +++ /dev/null @@ -1,19 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta - -import no.nav.paw.arbeidssokerregisteret.application.Opplysning -import no.nav.paw.pdl.graphql.generated.hentperson.Folkeregisterpersonstatus - -fun forenkletFregFakta(status: List): Set = - status.map { it.forenkletStatus } - .map { it.uppercase() } - .map { enkelFolkeRegStatusTilOpplysning[it] ?: Opplysning.UKJENT_FORENKLET_FREG_STATUS } - .toSet() - -private val enkelFolkeRegStatusTilOpplysning: Map = mapOf( - "bosattEtterFolkeregisterloven".uppercase() to Opplysning.BOSATT_ETTER_FREG_LOVEN, - "ikkeBosatt".uppercase() to Opplysning.IKKE_BOSATT, - "doedIFolkeregisteret".uppercase() to Opplysning.DOED, - "forsvunnet".uppercase() to Opplysning.SAVNET, - "opphoert".uppercase() to Opplysning.OPPHOERT_IDENTITET, - "dNummer".uppercase() to Opplysning.DNUMMER -) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/OppholdtillatelseFakta.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/OppholdtillatelseFakta.kt deleted file mode 100644 index ac106610..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/OppholdtillatelseFakta.kt +++ /dev/null @@ -1,22 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta - -import no.nav.paw.arbeidssokerregisteret.application.Opplysning -import no.nav.paw.pdl.graphql.generated.enums.Oppholdstillatelse -import no.nav.paw.pdl.graphql.generated.hentperson.Opphold -import java.time.LocalDate - - -fun oppholdstillatelseFakta(oppholdtillatelse: Opphold?): Opplysning { - val tilDato = oppholdtillatelse?.oppholdTil?.let(LocalDate::parse) - val utloept = tilDato?.isBefore(LocalDate.now()) ?: false - return if (utloept) { - Opplysning.OPPHOLDSTILATELSE_UTGAATT - } else - when (oppholdtillatelse?.type) { - Oppholdstillatelse.MIDLERTIDIG -> Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE - Oppholdstillatelse.PERMANENT -> Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE - Oppholdstillatelse.OPPLYSNING_MANGLER -> Opplysning.BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE - Oppholdstillatelse.__UNKNOWN_VALUE -> Opplysning.UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE - null -> Opplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE - } -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/InngangsRegler.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/InngangsRegler.kt deleted file mode 100644 index 4696ebe4..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/InngangsRegler.kt +++ /dev/null @@ -1,48 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.application.regler - -import no.nav.paw.arbeidssokerregisteret.application.* - -val reglerForInngangIPrioritertRekkefolge: List> = listOf( - "Person ikke funnet"( - Opplysning.PERSON_IKKE_FUNNET, - id = RegelId.IKKE_FUNNET, - vedTreff = ::Avvist - ), - "Er registrert som død"( - Opplysning.DOED, - id = RegelId.DOED, - vedTreff = ::Avvist - ), - "Er forhåndsgodkjent av ansatt"( - Opplysning.FORHAANDSGODKJENT_AV_ANSATT, - id = RegelId.FORHAANDSGODKJENT_AV_ANSATT, - vedTreff = ::OK - ), - "Er bosatt i Norge i henhold Folkeregisterloven, men er under 18 år"( - Opplysning.ER_UNDER_18_AAR, - Opplysning.BOSATT_ETTER_FREG_LOVEN, - id = RegelId.UNDER_18_AAR, - vedTreff = ::Avvist - ), - "Kunne ikke fastslå alder"( - Opplysning.UKJENT_FOEDSELSDATO, - Opplysning.UKJENT_FOEDSELSAAR, - id = RegelId.UKJENT_ALDER, - vedTreff = ::Avvist - ), - "Er registrert som savnet"( - Opplysning.SAVNET, - id = RegelId.SAVNET, - vedTreff = ::Avvist - ), - "Er over 18 år, er bosatt i Norge i henhold Folkeregisterloven"( - Opplysning.ER_OVER_18_AAR, - Opplysning.BOSATT_ETTER_FREG_LOVEN, - id = RegelId.OVER_18_AAR_OG_BOSATT_ETTER_FREG_LOVEN, - vedTreff = ::OK - ), - "Avvist fordi personen ikke er bosatt i Norge i henhold til folkeregisterloven"( - id = RegelId.IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN, - vedTreff = ::Avvist - ) -) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/TilgangsRegler.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/TilgangsRegler.kt index abbadaf6..883bceec 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/TilgangsRegler.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/regler/TilgangsRegler.kt @@ -1,37 +1,67 @@ package no.nav.paw.arbeidssokerregisteret.application.regler import no.nav.paw.arbeidssokerregisteret.application.* +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.* +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning -val tilgangsReglerIPrioritertRekkefolge: List> = listOf( +val tilgangsReglerIPrioritertRekkefolge: List = listOf( "Ansatt har tilgang til bruker"( - Opplysning.ANSATT_TILGANG, - id = RegelId.ANSATT_HAR_TILGANG_TIL_BRUKER, - vedTreff = ::TilgangOK + AuthOpplysning.AnsattTilgang, + id = AnsattHarTilgangTilBruker, + vedTreff = ::ok ), "Ikke ansatt har satt forhåndsgodkjenningAvVeileder"( - Opplysning.FORHAANDSGODKJENT_AV_ANSATT, - Opplysning.IKKE_ANSATT, - id = RegelId.IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT, - vedTreff = ::UgyldigRequestBasertPaaAutentisering + DomeneOpplysning.ErForhaandsgodkjent, + AuthOpplysning.IkkeAnsatt, + id = IkkeAnsattOgForhaandsgodkjentAvAnsatt, + vedTreff = ::problem ), "Bruker prøver å endre for seg selv"( - Opplysning.SAMME_SOM_INNLOGGET_BRUKER, - Opplysning.IKKE_ANSATT, - id = RegelId.ENDRE_EGEN_BRUKER, - vedTreff = ::TilgangOK + AuthOpplysning.SammeSomInnloggetBruker, + AuthOpplysning.IkkeAnsatt, + id = EndreEgenBruker, + vedTreff = ::ok ), "Prøver å endre for en annen bruker"( - Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER, - id = RegelId.ENDRE_FOR_ANNEN_BRUKER, - vedTreff = ::IkkeTilgang + AuthOpplysning.IkkeSammeSomInnloggerBruker, + id = EndreForAnnenBruker, + vedTreff = ::problem ), "Ansatt har ikke tilgang til bruker"( - Opplysning.ANSATT_IKKE_TILGANG, - id = RegelId.ANSATT_IKKE_TILGANG_TIL_BRUKER, - vedTreff = ::IkkeTilgang + AuthOpplysning.AnsattIkkeTilgang, + id = AnsattIkkeTilgangTilBruker, + vedTreff = ::problem ), "Ikke tilgang"( - id = RegelId.IKKE_TILGANG, - vedTreff = ::IkkeTilgang + id = IkkeTilgang, + vedTreff = ::problem ) ) + +sealed interface AuthRegelId: RegelId + +data object IkkeTilgang : AuthRegelId { + override val id: String = "IKKE_TILGANG" +} + +data object AnsattIkkeTilgangTilBruker : AuthRegelId { + override val id: String = "ANSATT_IKKE_TILGANG_TIL_BRUKER" +} + +data object EndreForAnnenBruker : AuthRegelId { + override val id: String = "ENDRE_FOR_ANNEN_BRUKER" +} + +data object EndreEgenBruker : AuthRegelId { + override val id: String = "ENDRE_EGEN_BRUKER" +} + +data object IkkeAnsattOgForhaandsgodkjentAvAnsatt : AuthRegelId { + override val id: String = "IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT" +} + +data object AnsattHarTilgangTilBruker : AuthRegelId { + override val id: String = "ANSATT_HAR_TILGANG_TIL_BRUKER" +} + + diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/Feilkode.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/Feilkode.kt deleted file mode 100644 index 5abfe64f..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/Feilkode.kt +++ /dev/null @@ -1,10 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.domain - -enum class Feilkode { - UKJENT_FEIL, - UVENTET_FEIL_MOT_EKSTERN_TJENESTE, - FEIL_VED_LESING_AV_FORESPORSEL, - AVVIST, - IKKE_TILGANG, - UGYLDIG_FORESPORSEL -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/Feil.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/Feil.kt deleted file mode 100644 index 01913b64..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/Feil.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.domain.http - -import no.nav.paw.arbeidssokerregisteret.application.EksternRegelId -import no.nav.paw.arbeidssokerregisteret.application.Opplysning -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode - -data class Feil( - val melding: String, - val feilKode: Feilkode, - val aarsakTilAvvisning: AarsakTilAvvisning? = null -) - -data class AarsakTilAvvisning( - val beskrivelse: String, - val regel: EksternRegelId, - val detaljer: Set -) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/StartStoppRequest.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/StartStoppRequest.kt deleted file mode 100644 index 5e253487..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/StartStoppRequest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.domain.http - -import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer -import no.nav.paw.arbeidssokerregisteret.domain.tilIdentitetsnummer - -data class StartStoppRequest( - val identitetsnummer: String, - val registreringForhaandsGodkjentAvAnsatt: Boolean = false, - val periodeTilstand: PeriodeTilstand -) { - fun getId(): Identitetsnummer = identitetsnummer.tilIdentitetsnummer() -} - -enum class PeriodeTilstand{ - STARTET, - STOPPET -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/ValidationResult.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/ValidationResult.kt deleted file mode 100644 index 78e11c75..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/ValidationResult.kt +++ /dev/null @@ -1,9 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.domain.http - -sealed interface ValidationResult -data object ValidationResultOk: ValidationResult - -data class ValidationErrorResult( - val fields: Set, - val message: String -): ValidationResult diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValidationResult.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValidationResult.kt new file mode 100644 index 00000000..fffb69d7 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValidationResult.kt @@ -0,0 +1,6 @@ +package no.nav.paw.arbeidssokerregisteret.domain.http.validering + +data class ValidationErrorResult( + val fields: Set, + val message: String +) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderBeskrivelser.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderBeskrivelser.kt index d1edcb6c..a8516a66 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderBeskrivelser.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderBeskrivelser.kt @@ -1,12 +1,12 @@ package no.nav.paw.arbeidssokerregisteret.domain.http.validering +import arrow.core.Either +import arrow.core.left +import arrow.core.right import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer.Beskrivelse.* -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationErrorResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResultOk -fun validerBeskrivelser(beskrivelser: List): ValidationResult { +fun validerBeskrivelser(beskrivelser: List): Either { val notValidWithAldriHattJobb = setOf( ER_PERMITTERT, DELTIDSJOBB_VIL_MER, @@ -20,10 +20,11 @@ fun validerBeskrivelser(beskrivelser: List return ValidationErrorResult( setOf("beskrivelser"), "Kan ikke ha beskrivelsene $notValidWithAldriHattJobb samtidig med $ALDRI_HATT_JOBB" - ) + ).left() } if (beskrivelser.contains(ER_PERMITTERT) && beskrivelser.contains(IKKE_VAERT_I_JOBB_SISTE_2_AAR)) { return ValidationErrorResult(setOf("beskrivelser"), "Kan ikke være permittert og ikke vært i jobb siste 2 år samtidig") + .left() } - return ValidationResultOk + return Unit.right() } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderJobbSituasjon.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderJobbSituasjon.kt index 7cbc59d0..ea3e3681 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderJobbSituasjon.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderJobbSituasjon.kt @@ -1,10 +1,10 @@ package no.nav.paw.arbeidssokerregisteret.domain.http.validering +import arrow.core.Either +import arrow.core.left import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Jobbsituasjon import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer.Beskrivelse.* import no.nav.paw.arbeidssokerregisteret.STILLING_STYRK08 -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationErrorResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResult /* UKJENT_VERDI @@ -24,7 +24,7 @@ KONKURS ANNET */ -fun validerJobbsituasjon(jobbsituasjon: Jobbsituasjon): ValidationResult { +fun validerJobbsituasjon(jobbsituasjon: Jobbsituasjon): Either { val requiresStyrk08 = setOf( ER_PERMITTERT, HAR_SAGT_OPP, @@ -41,14 +41,14 @@ fun validerJobbsituasjon(jobbsituasjon: Jobbsituasjon): ValidationResult { return ValidationErrorResult( setOf("jobbsituasjon.beskrivelser"), "Mangler '$STILLING_STYRK08' for ${missingStyrk08.joinToString { it.beskrivelse.name }}" - ) + ).left() } val detaljerError = jobbsituasjon.beskrivelser .map(::validerDetaljer) .filterIsInstance() if (detaljerError.isNotEmpty()){ - return detaljerError.first() + return detaljerError.first().left() } return validerBeskrivelser(jobbsituasjon.beskrivelser.map { it.beskrivelse }) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/OpplysningerRequest.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderOpplysninger.kt similarity index 55% rename from apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/OpplysningerRequest.kt rename to apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderOpplysninger.kt index a0918631..46573344 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/OpplysningerRequest.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderOpplysninger.kt @@ -1,12 +1,13 @@ -package no.nav.paw.arbeidssokerregisteret.domain.http +package no.nav.paw.arbeidssokerregisteret.domain.http.validering +import arrow.core.Either +import arrow.core.left +import arrow.core.right import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.OpplysningerOmArbeidssoeker -import no.nav.paw.arbeidssokerregisteret.domain.http.validering.validerJobbsituasjon -import no.nav.paw.arbeidssokerregisteret.domain.http.validering.validerUtdanning -fun validerOpplysninger(opplysningerOmArbeidssoeker: OpplysningerOmArbeidssoeker): ValidationResult = +fun validerOpplysninger(opplysningerOmArbeidssoeker: OpplysningerOmArbeidssoeker): Either = listOfNotNull( opplysningerOmArbeidssoeker.utdanning?.let(::validerUtdanning), validerJobbsituasjon(opplysningerOmArbeidssoeker.jobbsituasjon) ).filterIsInstance() - .firstOrNull() ?: ValidationResultOk + .firstOrNull()?.left() ?: Unit.right() diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderSituasjonDetaljer.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderSituasjonDetaljer.kt index ba80ca5b..5d71b617 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderSituasjonDetaljer.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderSituasjonDetaljer.kt @@ -1,10 +1,10 @@ package no.nav.paw.arbeidssokerregisteret.domain.http.validering +import arrow.core.Either +import arrow.core.left +import arrow.core.right import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Detaljer import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationErrorResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResultOk val validationRules = listOf( @@ -15,37 +15,37 @@ val validationRules = val ingenDetaljer: Detaljer = Detaljer(null, null, null) -fun validerDetaljer(situasjonMedDetaljer: JobbsituasjonMedDetaljer): ValidationResult = +fun validerDetaljer(situasjonMedDetaljer: JobbsituasjonMedDetaljer): Either = validationRules .mapNotNull { (property, rule) -> property(situasjonMedDetaljer.detaljer ?: ingenDetaljer) ?.let { rule(property.name, it) } }.filterIsInstance() - .firstOrNull() ?: ValidationResultOk + .firstOrNull()?.left() ?: Unit.right() -fun isValidPercentage(key: String, percent: String): ValidationResult = +fun isValidPercentage(key: String, percent: String): Either = try { val verdi = percent.toDouble() if (verdi > 0.0 && verdi <= 100.0) { - ValidationResultOk + Unit.right() } else { - ValidationErrorResult(setOf(key), "Prosent må være et tall mellom 0 og 100. Var $percent") + ValidationErrorResult(setOf(key), "Prosent må være et tall mellom 0 og 100. Var $percent").left() } } catch (e: Exception) { - ValidationErrorResult(setOf(key), "Prosent må være et tall mellom 0 og 100. Var $percent") + ValidationErrorResult(setOf(key), "Prosent må være et tall mellom 0 og 100. Var $percent").left() } -fun isNotEmptyString(key: String, string: String): ValidationResult = +fun isNotEmptyString(key: String, string: String): Either = if (string.isNotBlank()) { - ValidationResultOk + Unit.right() } else { - ValidationErrorResult(setOf(key), "$key kan ikke være tom") + ValidationErrorResult(setOf(key), "$key kan ikke være tom").left() } -fun validateStyrk08(key: String, styrk: String): ValidationResult = +fun validateStyrk08(key: String, styrk: String): Either = if (Regex("[0-9]{1,4}").matches(styrk)) { - ValidationResultOk + Unit.right() } else { - ValidationErrorResult(setOf(key), "Styrk08 må være 1-4 siffer. Styrk08 var $styrk") + ValidationErrorResult(setOf(key), "Styrk08 må være 1-4 siffer. Styrk08 var $styrk").left() } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderUtdanning.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderUtdanning.kt index f1195651..c6817b28 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderUtdanning.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/domain/http/validering/ValiderUtdanning.kt @@ -1,9 +1,9 @@ package no.nav.paw.arbeidssokerregisteret.domain.http.validering +import arrow.core.Either +import arrow.core.left +import arrow.core.right import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Utdanning -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationErrorResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResult -import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResultOk /* 0 - Ingen utdanning og førskoleutdanning @@ -17,20 +17,20 @@ import no.nav.paw.arbeidssokerregisteret.domain.http.ValidationResultOk 8 - Forskerutdanning 9 - Uoppgitt */ -fun validerUtdanning(utdanning: Utdanning): ValidationResult { +fun validerUtdanning(utdanning: Utdanning): Either { val nus = utdanning.nus val forventerBestaattOgGodkjent = setOf("3", "4", "5", "6", "7", "8") if (!Regex("[0-9]").matches(nus)) { - return ValidationErrorResult(setOf("nus"), "Nus må være 0-9. Nus var $nus") + return ValidationErrorResult(setOf("nus"), "Nus må være 0-9. Nus var $nus").left() } if (nus !in forventerBestaattOgGodkjent) { if (utdanning.bestaatt != null || utdanning.godkjent != null) { - return ValidationErrorResult(setOf("nus", "bestaatt", "godkjent"), "Forventer ikke svar på bestått eller godkjent ved nus $nus") + return ValidationErrorResult(setOf("nus", "bestaatt", "godkjent"), "Forventer ikke svar på bestått eller godkjent ved nus $nus").left() } } else { if (utdanning.bestaatt == null || utdanning.godkjent == null) { - return ValidationErrorResult(setOf("nus", "bestatt", "godkjent"), "Forventer svar på bestatt og godkjent ved nus $nus") + return ValidationErrorResult(setOf("nus", "bestatt", "godkjent"), "Forventer svar på bestatt og godkjent ved nus $nus").left() } } - return ValidationResultOk + return Unit.right() } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/ArbeidssoekerException.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/ArbeidssoekerException.kt index 63f6e281..c21d279d 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/ArbeidssoekerException.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/ArbeidssoekerException.kt @@ -1,12 +1,29 @@ package no.nav.paw.arbeidssokerregisteret.plugins import io.ktor.http.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode +import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Feil abstract class ArbeidssoekerException( val status: HttpStatusCode, description: String? = null, - val feilkode: Feilkode, + val feilkode: InternFeilkode, causedBy: Throwable? = null ) : Exception("Request failed with status: $status. Description: $description. ErrorCode: $feilkode", causedBy) +enum class InternFeilkode { + UVENTET_FEIL_MOT_EKSTERN_TJENESTE + +} + +fun InternFeilkode.opplysningerFeilkode(): Feil.FeilKode { + when (this) { + InternFeilkode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE -> return Feil.FeilKode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE + + } +} + +fun InternFeilkode.startStoppFeilkode(): no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil.FeilKode { + when (this) { + InternFeilkode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE -> return no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil.FeilKode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE + } +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/HTTP.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/HTTP.kt index 913222be..9cee77ab 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/HTTP.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/HTTP.kt @@ -1,75 +1,146 @@ package no.nav.paw.arbeidssokerregisteret.plugins import com.fasterxml.jackson.databind.DatabindException -import io.ktor.http.HttpStatusCode -import io.ktor.server.application.Application -import io.ktor.server.application.install -import io.ktor.server.plugins.BadRequestException +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.plugins.* import io.ktor.server.plugins.ContentTransformationException -import io.ktor.server.plugins.cors.routing.CORS -import io.ktor.server.plugins.statuspages.StatusPages -import io.ktor.server.request.RequestAlreadyConsumedException -import io.ktor.server.response.respond -import io.ktor.server.routing.IgnoreTrailingSlash -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode -import no.nav.paw.arbeidssokerregisteret.domain.http.Feil +import io.ktor.server.plugins.cors.routing.* +import io.ktor.server.plugins.statuspages.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.routes.kanStarte +import no.nav.paw.arbeidssokerregisteret.routes.opplysninger +import no.nav.paw.arbeidssokerregisteret.routes.periode +import no.nav.paw.arbeidssokerregisteret.routes.startStopApi import no.nav.paw.arbeidssokerregisteret.services.RemoteServiceException import no.nav.paw.arbeidssokerregisteret.utils.logger +import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Feil as OpplysningerFeil +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil as StartStoppFeil + +fun ApplicationCall.isStartStopRequest(): Boolean = request.path().startsWith("$startStopApi$periode") +fun ApplicationCall.isKanStarteRequest(): Boolean = request.path().startsWith("$startStopApi$kanStarte") +fun ApplicationCall.isOpplysningerMottattRequest(): Boolean = request.path().startsWith("$startStopApi$opplysninger") fun Application.configureHTTP() { install(IgnoreTrailingSlash) + install(CORS) { + anyHost() + + allowMethod(HttpMethod.Options) + allowMethod(HttpMethod.Put) + allowMethod(HttpMethod.Patch) + allowMethod(HttpMethod.Delete) + + allowHeader(HttpHeaders.Authorization) + allowHeader(HttpHeaders.ContentType) + allowHeader(HttpHeaders.AccessControlAllowOrigin) + + allowHeadersPrefixed("nav-") + } install(StatusPages) { exception { call, cause -> when (cause) { - is ContentTransformationException -> { + is ContentTransformationException, + is DatabindException, + is BadRequestException -> { logger.debug("Bad request", cause) - call.respond(HttpStatusCode.BadRequest, Feil(cause.message ?: "Bad request", Feilkode.FEIL_VED_LESING_AV_FORESPORSEL)) - } + when { + call.isStartStopRequest() || + call.isKanStarteRequest() -> call.respond( + HttpStatusCode.BadRequest, + StartStoppFeil( + melding = cause.message ?: "Bad request", + feilKode = StartStoppFeil.FeilKode.FEIL_VED_LESING_AV_FORESPORSEL + ) + ) - is DatabindException -> { - logger.debug("Bad request", cause) - call.respond(HttpStatusCode.BadRequest, Feil(cause.message ?: "Bad request", Feilkode.FEIL_VED_LESING_AV_FORESPORSEL)) + call.isOpplysningerMottattRequest() -> call.respond( + HttpStatusCode.BadRequest, + OpplysningerFeil( + melding = cause.message ?: "Bad request", + feilKode = OpplysningerFeil.FeilKode.FEIL_VED_LESING_AV_FORESPORSEL + ) + ) + + else -> call.respond(HttpStatusCode.BadRequest) + } } is RemoteServiceException -> { logger.warn("Request failed with status: ${cause}. Description: ${cause.message}") - call.respond(cause.status, Feil(cause.message ?: "ukjent feil knyttet til eksternt system", cause.feilkode)) + when { + call.isStartStopRequest() || + call.isKanStarteRequest() -> call.respond( + HttpStatusCode.ServiceUnavailable, + StartStoppFeil( + melding = cause.message ?: "Remote call failed", + feilKode = StartStoppFeil.FeilKode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE + ) + ) + + call.isOpplysningerMottattRequest() -> call.respond( + HttpStatusCode.ServiceUnavailable, + OpplysningerFeil( + melding = cause.message ?: "Remote call failed", + feilKode = OpplysningerFeil.FeilKode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE + ) + ) + + else -> call.respond(HttpStatusCode.BadRequest) + } } is StatusException -> { logger.error("Request failed with status: ${cause}. Description: ${cause.message}") - call.respond(cause.status, Feil(cause.message ?: "ukjent feil", cause.feilkode)) - } + when { + call.isStartStopRequest() || + call.isKanStarteRequest() -> call.respond( + cause.status, + StartStoppFeil( + melding = cause.message ?: "Unknown error", + feilKode = cause.feilkode.startStoppFeilkode() + ) + ) - is BadRequestException -> { - logger.error("Request failed: ${cause.message}", cause) - call.respond(HttpStatusCode.BadRequest, Feil(cause.message ?: "bad request", Feilkode.FEIL_VED_LESING_AV_FORESPORSEL)) - } + call.isOpplysningerMottattRequest() -> call.respond( + cause.status, + OpplysningerFeil( + melding = cause.message ?: "Unknown error", + feilKode = cause.feilkode.opplysningerFeilkode() + ) + ) - is RequestAlreadyConsumedException -> { - logger.error("Request failed: {}", cause.message, cause) - call.respond(HttpStatusCode.InternalServerError, Feil(cause.message ?: "bad request", Feilkode.UKJENT_FEIL)) + else -> call.respond(HttpStatusCode.BadRequest) + } } else -> { logger.error("Request failed with status: ${cause}. Description: ${cause.message}") - call.respond(HttpStatusCode.InternalServerError, Feil(cause.message ?: "ukjent feil", Feilkode.UKJENT_FEIL)) + when { + call.isStartStopRequest() || + call.isKanStarteRequest() -> call.respond( + HttpStatusCode.InternalServerError, + StartStoppFeil( + melding = cause.message ?: "Unknown error", + feilKode = Feil.FeilKode.UKJENT_FEIL + ) + ) + + call.isOpplysningerMottattRequest() -> call.respond( + HttpStatusCode.InternalServerError, + OpplysningerFeil( + melding = cause.message ?: "Unknown error", + feilKode = OpplysningerFeil.FeilKode.UKJENT_FEIL + ) + ) + + else -> call.respond(HttpStatusCode.BadRequest) + } } } } } - install(CORS) { - anyHost() - - allowMethod(io.ktor.http.HttpMethod.Options) - allowMethod(io.ktor.http.HttpMethod.Put) - allowMethod(io.ktor.http.HttpMethod.Patch) - allowMethod(io.ktor.http.HttpMethod.Delete) - - allowHeader(io.ktor.http.HttpHeaders.Authorization) - allowHeader(io.ktor.http.HttpHeaders.ContentType) - allowHeader(io.ktor.http.HttpHeaders.AccessControlAllowOrigin) - - allowHeadersPrefixed("nav-") - } } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/StatusException.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/StatusException.kt index 2741df2b..aec4b4b3 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/StatusException.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/plugins/StatusException.kt @@ -1,10 +1,9 @@ package no.nav.paw.arbeidssokerregisteret.plugins import io.ktor.http.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode class StatusException( status: HttpStatusCode, beskrivelse: String? = null, - feilkode: Feilkode + feilkode: InternFeilkode ) : ArbeidssoekerException(status, beskrivelse, feilkode) diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ArbeidssokerRoutes.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ArbeidssokerRoutes.kt index 90d6e5eb..d87f7c52 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ArbeidssokerRoutes.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ArbeidssokerRoutes.kt @@ -8,17 +8,22 @@ import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1Arbeidssoke import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1ArbeidssokerPeriodePutRequest import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand import no.nav.paw.arbeidssokerregisteret.api.extensions.getId -import no.nav.paw.arbeidssokerregisteret.application.* +import no.nav.paw.arbeidssokerregisteret.application.OpplysningerRequestHandler +import no.nav.paw.arbeidssokerregisteret.application.StartStoppRequestHandler import no.nav.paw.arbeidssokerregisteret.requestScope import no.nav.paw.arbeidssokerregisteret.utils.logger -import java.util.* + +const val startStopApi = "/api/v1/arbeidssoker" +const val kanStarte = "/kanStartePeriode" +const val periode = "/periode" +const val opplysninger = "/opplysninger" fun Route.arbeidssokerRoutes( startStoppRequestHandler: StartStoppRequestHandler, opplysningerRequestHandler: OpplysningerRequestHandler ) { - route("/api/v1/arbeidssoker") { - route("/kanStartePeriode") { + route(startStopApi) { + route(kanStarte) { // Sjekker om bruker kan registreres som arbeidssøker put { request -> val resultat = with(requestScope()) { @@ -29,7 +34,7 @@ fun Route.arbeidssokerRoutes( } } - route("/periode") { + route(periode) { // Registrerer bruker som arbeidssøker put { startStoppRequest -> val resultat = with(requestScope()) { @@ -44,13 +49,10 @@ fun Route.arbeidssokerRoutes( } } logger.debug("Registreringsresultat: {}", resultat) - when (resultat) { - is TilgangskontrollResultat -> respondWith(resultat) - is EndeligResultat -> respondWith(resultat) - } + respondWith(resultat) } } - route("/opplysninger") { + route(opplysninger) { // Registrerer eller oppdaterer brukers opplysninger post { val opplysningerRequest = call.receive() @@ -59,10 +61,7 @@ fun Route.arbeidssokerRoutes( opplysningerRequestHandler.opprettBrukeropplysninger(opplysningerRequest) } logger.debug("Oppdateringsresultat: {}", resultat) - when (resultat) { - is Left -> ikkeTilgangTilResponse(resultat.value) - is Right -> respondWith(resultat.value) - } + respondWith(resultat) } } } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/OpplysningerResultatMapping.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/OpplysningerResultatMapping.kt new file mode 100644 index 00000000..26c6ffc9 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/OpplysningerResultatMapping.kt @@ -0,0 +1,22 @@ +package no.nav.paw.arbeidssokerregisteret.routes + +import arrow.core.Either +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.response.* +import io.ktor.util.pipeline.* +import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.Feil + +context(PipelineContext) +suspend fun respondWith(resultat: Either) = + when (resultat) { + is Either.Left -> call.respond(resultat.value.feilKode.httpStatusCode(), ) + is Either.Right -> call.respond(HttpStatusCode.Accepted) + } + +fun Feil.FeilKode.httpStatusCode(): HttpStatusCode = when (this) { + Feil.FeilKode.UKJENT_FEIL -> HttpStatusCode.InternalServerError + Feil.FeilKode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE -> HttpStatusCode.FailedDependency + Feil.FeilKode.FEIL_VED_LESING_AV_FORESPORSEL -> HttpStatusCode.BadRequest + Feil.FeilKode.IKKE_TILGANG -> HttpStatusCode.Forbidden +} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ResultToResponse.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ResultToResponse.kt deleted file mode 100644 index b49e2cc1..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ResultToResponse.kt +++ /dev/null @@ -1,56 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.routes - -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.response.* -import io.ktor.util.pipeline.* -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.StatusCode -import io.opentelemetry.instrumentation.annotations.WithSpan -import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode -import no.nav.paw.arbeidssokerregisteret.domain.http.AarsakTilAvvisning -import no.nav.paw.arbeidssokerregisteret.domain.http.Feil - -context(PipelineContext) -@WithSpan -suspend fun respondWith(resultat: EndeligResultat) { - val otelStatusCode = if (resultat is OK) StatusCode.OK else StatusCode.ERROR - Span.current() - .setStatus(otelStatusCode, resultat::class.simpleName!!) - when (resultat) { - is Avvist -> call.respond( - HttpStatusCode.Forbidden, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.AVVIST, - aarsakTilAvvisning = AarsakTilAvvisning( - beskrivelse = resultat.regel.beskrivelse, - regel = resultat.regel.id.eksternRegelId ?: EksternRegelId.UKJENT_REGEL, - detaljer = resultat.opplysning.toSet() - ) - ) - ) - - is IkkeTilgang -> call.respond( - HttpStatusCode.Forbidden, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.IKKE_TILGANG - ) - ) - - is OK -> call.respond(HttpStatusCode.NoContent) - is Uavklart -> call.respond( - HttpStatusCode.Forbidden, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.AVVIST - ) - ) - - is UgyldigRequestBasertPaaAutentisering -> call.respond( - HttpStatusCode.BadRequest, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.UGYLDIG_FORESPORSEL - ) - ) - } -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/StartStoppResultatMapping.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/StartStoppResultatMapping.kt new file mode 100644 index 00000000..283168fa --- /dev/null +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/StartStoppResultatMapping.kt @@ -0,0 +1,129 @@ +package no.nav.paw.arbeidssokerregisteret.routes + +import arrow.core.Either +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.response.* +import io.ktor.util.pipeline.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.AarsakTilAvvisning +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiRegelId +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.application.* +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.* +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.* +import no.nav.paw.arbeidssokerregisteret.application.regler.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Opplysning as ApiOpplysning + + +context(PipelineContext) +suspend fun respondWith(resultat: Either) = + when (resultat) { + is Either.Left -> respondWithError(resultat.value) + is Either.Right -> call.respond(HttpStatusCode.NoContent) + } + +suspend fun PipelineContext.respondWithError(problem: Problem){ + call.respond( + problem.httpCode(), Feil( + melding = problem.regel.beskrivelse, + feilKode = problem.feilKode(), + aarsakTilAvvisning = if (problem.regel.id is DomeneRegelId) { + AarsakTilAvvisning( + beskrivelse = problem.regel.beskrivelse, + regel = problem.regel.id.apiRegelId(), + detaljer = problem.opplysning.map(::opplysningTilApiOpplysning) + ) + } else null + ) + ) +} + +fun opplysningTilApiOpplysning(opplysning: Opplysning): ApiOpplysning = + when (opplysning) { + is DomeneOpplysning -> when (opplysning) { + DomeneOpplysning.BarnFoedtINorgeUtenOppholdstillatelse -> ApiOpplysning.BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE + DomeneOpplysning.BosattEtterFregLoven -> ApiOpplysning.BOSATT_ETTER_FREG_LOVEN + DomeneOpplysning.Dnummer -> ApiOpplysning.DNUMMER + DomeneOpplysning.ErDoed -> ApiOpplysning.DOED + DomeneOpplysning.ErEuEoesStatsborger -> ApiOpplysning.ER_EU_EOES_STATSBORGER + DomeneOpplysning.ErForhaandsgodkjent -> ApiOpplysning.FORHAANDSGODKJENT_AV_ANSATT + DomeneOpplysning.ErGbrStatsborger -> ApiOpplysning.ER_GBR_STATSBORGER + DomeneOpplysning.ErOver18Aar -> ApiOpplysning.ER_OVER_18_AAR + DomeneOpplysning.ErSavnet -> ApiOpplysning.SAVNET + DomeneOpplysning.ErUnder18Aar -> ApiOpplysning.ER_UNDER_18_AAR + DomeneOpplysning.HarGyldigOppholdstillatelse -> ApiOpplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE + DomeneOpplysning.HarNorskAdresse -> ApiOpplysning.HAR_NORSK_ADRESSE + DomeneOpplysning.HarUtenlandskAdresse -> ApiOpplysning.HAR_UTENLANDSK_ADRESSE + DomeneOpplysning.IkkeBosatt -> ApiOpplysning.IKKE_BOSATT + DomeneOpplysning.IkkeMuligAAIdentifisereSisteFlytting -> ApiOpplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING + DomeneOpplysning.IngenAdresseFunnet -> ApiOpplysning.INGEN_ADRESSE_FUNNET + DomeneOpplysning.IngenFlytteInformasjon -> ApiOpplysning.INGEN_FLYTTE_INFORMASJON + DomeneOpplysning.IngenInformasjonOmOppholdstillatelse -> ApiOpplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE + DomeneOpplysning.OpphoertIdentitet -> ApiOpplysning.OPPHOERT_IDENTITET + DomeneOpplysning.OppholdstillatelseUtgaaatt -> ApiOpplysning.OPPHOLDSTILATELSE_UTGAATT + DomeneOpplysning.PersonIkkeFunnet -> ApiOpplysning.PERSON_IKKE_FUNNET + DomeneOpplysning.SisteFlyttingVarInnTilNorge -> ApiOpplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE + DomeneOpplysning.SisteFlyttingVarUtAvNorge -> ApiOpplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE + DomeneOpplysning.TokenxPidIkkeFunnet -> ApiOpplysning.TOKENX_PID_IKKE_FUNNET + DomeneOpplysning.UkjentFoedselsaar -> ApiOpplysning.UKJENT_FOEDSELSAAR + DomeneOpplysning.UkjentFoedselsdato -> ApiOpplysning.UKJENT_FOEDSELSDATO + DomeneOpplysning.UkjentForenkletFregStatus -> ApiOpplysning.UKJENT_FORENKLET_FREG_STATUS + DomeneOpplysning.UkjentStatusForOppholdstillatelse -> ApiOpplysning.UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE + } + is AuthOpplysning -> when (opplysning) { + AuthOpplysning.IkkeSammeSomInnloggerBruker -> ApiOpplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER + AuthOpplysning.SammeSomInnloggetBruker -> ApiOpplysning.SAMME_SOM_INNLOGGET_BRUKER + AuthOpplysning.TokenXPidIkkeFunnet -> ApiOpplysning.TOKENX_PID_IKKE_FUNNET + AuthOpplysning.AnsattIkkeTilgang -> ApiOpplysning.ANSATT_IKKE_TILGANG + AuthOpplysning.AnsattTilgang -> ApiOpplysning.ANSATT_TILGANG + AuthOpplysning.IkkeAnsatt -> ApiOpplysning.IKKE_ANSATT + } + else -> ApiOpplysning.UKJENT_OPPLYSNING + } + +fun RegelId.apiRegelId(): ApiRegelId = when (this) { + is AuthRegelId -> ApiRegelId.IKKE_TILGANG + is DomeneRegelId -> when(this) { + ForhaandsgodkjentAvAnsatt -> ApiRegelId.UKJENT_REGEL + Over18AarOgBosattEtterFregLoven -> ApiRegelId.UKJENT_REGEL + Doed -> ApiRegelId.DOED + IkkeBosattINorgeIHenholdTilFolkeregisterloven -> ApiRegelId.IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN + IkkeFunnet -> ApiRegelId.IKKE_FUNNET + Savnet -> ApiRegelId.SAVNET + UkjentAlder -> ApiRegelId.UKJENT_ALDER + Under18Aar -> ApiRegelId.UNDER_18_AAR + } + else -> ApiRegelId.UKJENT_REGEL +} + +fun Problem.feilKode(): Feil.FeilKode = when (regel.id) { + is AuthRegelId -> Feil.FeilKode.IKKE_TILGANG + is DomeneRegelId -> Feil.FeilKode.AVVIST + else -> Feil.FeilKode.UKJENT_FEIL +} + +fun Problem.httpCode(): HttpStatusCode = when (val regelId = this.regel.id) { + is AuthRegelId -> regelId.httpCode() + is DomeneRegelId -> regelId.httpCode() + else -> HttpStatusCode.InternalServerError +} + +fun AuthRegelId.httpCode(): HttpStatusCode = when (this) { + AnsattHarTilgangTilBruker -> HttpStatusCode.OK + EndreEgenBruker -> HttpStatusCode.OK + AnsattIkkeTilgangTilBruker -> HttpStatusCode.Forbidden + EndreForAnnenBruker -> HttpStatusCode.Forbidden + IkkeAnsattOgForhaandsgodkjentAvAnsatt -> HttpStatusCode.BadRequest + IkkeTilgang -> HttpStatusCode.Forbidden +} + +fun DomeneRegelId.httpCode(): HttpStatusCode = when (this) { + ForhaandsgodkjentAvAnsatt -> HttpStatusCode.Accepted + Over18AarOgBosattEtterFregLoven -> HttpStatusCode.Accepted + Doed -> HttpStatusCode.Forbidden + IkkeBosattINorgeIHenholdTilFolkeregisterloven -> HttpStatusCode.Forbidden + IkkeFunnet -> HttpStatusCode.Forbidden + Savnet -> HttpStatusCode.Forbidden + UkjentAlder -> HttpStatusCode.Forbidden + Under18Aar -> HttpStatusCode.Forbidden +} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/TilgangskontrolResultatTilResponse.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/TilgangskontrolResultatTilResponse.kt deleted file mode 100644 index 7ce02340..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/TilgangskontrolResultatTilResponse.kt +++ /dev/null @@ -1,51 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.routes - -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.response.* -import io.ktor.util.pipeline.* -import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode -import no.nav.paw.arbeidssokerregisteret.domain.http.AarsakTilAvvisning -import no.nav.paw.arbeidssokerregisteret.domain.http.Feil - - -context(PipelineContext) -suspend fun respondWith(resultat: TilgangskontrollResultat) = - when (resultat) { - is IkkeTilgang -> ikkeTilgangTilResponse(resultat) - is UgyldigRequestBasertPaaAutentisering -> ugyldigRequestBasertPaaAutentiseringResponse(resultat) - is TilgangOK -> call.respond(HttpStatusCode.NoContent) - } - -suspend fun PipelineContext.ikkeTilgangTilResponse( - resultat: TilgangskontrollResultat -) { - call.respond( - HttpStatusCode.Forbidden, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.AVVIST, - aarsakTilAvvisning = AarsakTilAvvisning( - beskrivelse = resultat.regel.beskrivelse, - regel = resultat.regel.id.eksternRegelId ?: EksternRegelId.UKJENT_REGEL, - detaljer = resultat.regel.opplysninger.toSet() - ) - ) - ) -} - -suspend fun PipelineContext.ugyldigRequestBasertPaaAutentiseringResponse( - resultat: TilgangskontrollResultat -) { - call.respond( - HttpStatusCode.BadRequest, Feil( - melding = resultat.regel.beskrivelse, - feilKode = Feilkode.UGYLDIG_FORESPORSEL, - aarsakTilAvvisning = AarsakTilAvvisning( - beskrivelse = resultat.regel.beskrivelse, - regel = resultat.regel.id.eksternRegelId ?: EksternRegelId.UKJENT_REGEL, - detaljer = resultat.regel.opplysninger.toSet() - ) - ) - ) -} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ValidationResultToResponse.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ValidationResultToResponse.kt deleted file mode 100644 index 2625ed0a..00000000 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/routes/ValidationResultToResponse.kt +++ /dev/null @@ -1,21 +0,0 @@ -package no.nav.paw.arbeidssokerregisteret.routes - -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.response.* -import io.ktor.util.pipeline.* -import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode -import no.nav.paw.arbeidssokerregisteret.domain.http.* - -context(PipelineContext) -suspend fun respondWith(resultat: ValidationResult) = - when (resultat) { - is ValidationErrorResult -> call.respond( - HttpStatusCode.BadRequest, Feil( - melding = "felter=${resultat.fields} => ${resultat.message}", - feilKode = Feilkode.FEIL_VED_LESING_AV_FORESPORSEL - ) - ) - ValidationResultOk -> call.respond(HttpStatusCode.Accepted) - } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/PersonInfoService.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/PersonInfoService.kt index a86205b3..4d0213d1 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/PersonInfoService.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/PersonInfoService.kt @@ -1,7 +1,7 @@ package no.nav.paw.arbeidssokerregisteret.services import no.nav.paw.arbeidssokerregisteret.RequestScope -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode +import no.nav.paw.arbeidssokerregisteret.plugins.InternFeilkode import no.nav.paw.pdl.PdlClient import no.nav.paw.pdl.PdlException import no.nav.paw.pdl.graphql.generated.hentperson.Person @@ -25,7 +25,7 @@ class PersonInfoService( } catch (ex: PdlException) { throw RemoteServiceException( description = "Feil ved henting av personinfo fra PDL", - feilkode = Feilkode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE, + feilkode = InternFeilkode.UVENTET_FEIL_MOT_EKSTERN_TJENESTE, causedBy = ex ) } diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/RemoteServiceException.kt b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/RemoteServiceException.kt index 1c5d299d..6f003275 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/RemoteServiceException.kt +++ b/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/services/RemoteServiceException.kt @@ -2,10 +2,10 @@ package no.nav.paw.arbeidssokerregisteret.services import io.ktor.http.* import no.nav.paw.arbeidssokerregisteret.plugins.ArbeidssoekerException -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode +import no.nav.paw.arbeidssokerregisteret.plugins.InternFeilkode class RemoteServiceException( description: String? = null, - feilkode: Feilkode, + feilkode: InternFeilkode, causedBy: Throwable? = null ) : ArbeidssoekerException(HttpStatusCode.FailedDependency, description, feilkode, causedBy) diff --git a/apps/api-start-stopp-perioder/src/main/resources/openapi/opplysninger.yaml b/apps/api-start-stopp-perioder/src/main/resources/openapi/opplysninger.yaml index 7aa35f12..0cc941bb 100644 --- a/apps/api-start-stopp-perioder/src/main/resources/openapi/opplysninger.yaml +++ b/apps/api-start-stopp-perioder/src/main/resources/openapi/opplysninger.yaml @@ -196,37 +196,3 @@ components: siste_arbeidsdag_iso8601: type: "string" format: "date" - Opplysning: - type: "string" - enum: - - "FORHAANDSGODKJENT_AV_ANSATT" - - "SAMME_SOM_INNLOGGET_BRUKER" - - "IKKE_SAMME_SOM_INNLOGGER_BRUKER" - - "ANSATT_IKKE_TILGANG" - - "ANSATT_TILGANG" - - "IKKE_ANSATT" - - "ER_OVER_18_AAR" - - "ER_UNDER_18_AAR" - - "UKJENT_FOEDSELSDATO" - - "UKJENT_FOEDSELSAAR" - - "TOKENX_PID_IKKE_FUNNET" - - "OPPHOERT_IDENTITET" - - "IKKE_BOSATT" - - "DOED" - - "SAVNET" - - "HAR_NORSK_ADRESSE" - - "HAR_UTENLANDSK_ADRESSE" - - "INGEN_ADRESSE_FUNNET" - - "BOSATT_ETTER_FREG_LOVEN" - - "DNUMMER" - - "UKJENT_FORENKLET_FREG_STATUS" - - "HAR_GYLDIG_OPPHOLDSTILLATELSE" - - "OPPHOLDSTILATELSE_UTGAATT" - - "BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE" - - "INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE" - - "UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE" - - "PERSON_IKKE_FUNNET" - - "SISTE_FLYTTING_VAR_UT_AV_NORGE" - - "SISTE_FLYTTING_VAR_INN_TIL_NORGE" - - "IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING" - - "INGEN_FLYTTE_INFORMASJON" \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/main/resources/openapi/startstopp.yaml b/apps/api-start-stopp-perioder/src/main/resources/openapi/startstopp.yaml index b1321a01..fdb5007b 100644 --- a/apps/api-start-stopp-perioder/src/main/resources/openapi/startstopp.yaml +++ b/apps/api-start-stopp-perioder/src/main/resources/openapi/startstopp.yaml @@ -178,18 +178,7 @@ components: beskrivelse: type: "string" regel: - type: "string" - enum: - - "UKJENT_REGEL" - - "IKKE_FUNNET" - - "SAVNET" - - "DOED" - - "ENDRE_FOR_ANNEN_BRUKER" - - "ANSATT_IKKE_TILGANG_TIL_BRUKER" - - "IKKE_TILGANG" - - "UNDER_18_AAR" - - "IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN" - - "UKJENT_ALDER" + $ref: "#/components/schemas/ApiRegelId" detaljer: type: "array" items: @@ -232,3 +221,19 @@ components: - "SISTE_FLYTTING_VAR_INN_TIL_NORGE" - "IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING" - "INGEN_FLYTTE_INFORMASJON" + - "ER_GBR_STATSBORGER" + - "ER_EU_EOES_STATSBORGER" + - "UKJENT_OPPLYSNING" + ApiRegelId: + type: "string" + enum: + - "UKJENT_REGEL" + - "IKKE_FUNNET" + - "SAVNET" + - "DOED" + - "ENDRE_FOR_ANNEN_BRUKER" + - "ANSATT_IKKE_TILGANG_TIL_BRUKER" + - "IKKE_TILGANG" + - "UNDER_18_AAR" + - "IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN" + - "UKJENT_ALDER" \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationOpplysningerTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationOpplysningerTest.kt index fe7b5198..8805f3e8 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationOpplysningerTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationOpplysningerTest.kt @@ -1,11 +1,11 @@ package no.nav.paw.arbeidssokerregisteret +import arrow.core.right import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.registerKotlinModule import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe -import io.ktor.client.call.* -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.jackson.* @@ -13,17 +13,15 @@ import io.ktor.server.testing.* import io.mockk.coEvery import io.mockk.coVerify import io.mockk.mockk -import io.mockk.verify import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.* import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer.Beskrivelse.DELTIDSJOBB_VIL_MER import no.nav.paw.arbeidssoekerregisteret.api.opplysningermottatt.models.JobbsituasjonMedDetaljer.Beskrivelse.HAR_SAGT_OPP -import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.domain.http.* +import no.nav.paw.arbeidssokerregisteret.application.OpplysningerRequestHandler +import no.nav.paw.arbeidssokerregisteret.application.StartStoppRequestHandler import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes import java.time.LocalDate -import kotlin.math.exp class ApplicationOpplysningerTest : FunSpec({ test("Verifiser opplysninger happy path") { @@ -39,7 +37,7 @@ class ApplicationOpplysningerTest : FunSpec({ with(any()) { opplysningerRequestHandler.opprettBrukeropplysninger(any()) } - } returns Right(ValidationResultOk) + } returns Unit.right() arbeidssokerRoutes(startStopppRequestHandler, opplysningerRequestHandler) } val client = createClient { diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationPeriodeTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationPeriodeTest.kt index d248cbd2..97767a3b 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationPeriodeTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationPeriodeTest.kt @@ -1,23 +1,21 @@ package no.nav.paw.arbeidssokerregisteret +import arrow.core.left import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.registerKotlinModule import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.ktor.client.call.* -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.jackson.* import io.ktor.server.testing.* import io.mockk.coEvery import io.mockk.mockk +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.* import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.domain.Feilkode -import no.nav.paw.arbeidssokerregisteret.domain.http.AarsakTilAvvisning -import no.nav.paw.arbeidssokerregisteret.domain.http.Feil -import no.nav.paw.arbeidssokerregisteret.domain.http.PeriodeTilstand -import no.nav.paw.arbeidssokerregisteret.domain.http.StartStoppRequest +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes @@ -35,15 +33,15 @@ class ApplicationPeriodeTest : FunSpec({ with(any()) { startStoppRequestHandler.startArbeidssokerperiode(any(), any()) } - } returns Avvist( + } returns Problem( regel = Regel( - id = RegelId.UNDER_18_AAR, + id = Under18Aar, beskrivelse = "under 18 år", - opplysninger = listOf(Opplysning.ER_UNDER_18_AAR), - vedTreff = ::Avvist + opplysninger = listOf(DomeneOpplysning.ErUnder18Aar), + vedTreff = ::problem ), - opplysning = listOf(Opplysning.ER_UNDER_18_AAR, Opplysning.BOSATT_ETTER_FREG_LOVEN) - ) + opplysning = listOf(DomeneOpplysning.ErUnder18Aar, DomeneOpplysning.BosattEtterFregLoven) + ).left() arbeidssokerRoutes(startStoppRequestHandler, mockk()) } val client = createClient { @@ -59,19 +57,19 @@ class ApplicationPeriodeTest : FunSpec({ append(HttpHeaders.ContentType, ContentType.Application.Json) } setBody( - StartStoppRequest( + ApiV1ArbeidssokerPeriodePutRequest( identitetsnummer = "12345678911", - periodeTilstand = PeriodeTilstand.STARTET + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET ) ) } response.status shouldBe HttpStatusCode.Forbidden val feil: Feil = response.body() feil shouldBe Feil( - "under 18 år", Feilkode.AVVIST, AarsakTilAvvisning( + "under 18 år", Feil.FeilKode.AVVIST, AarsakTilAvvisning( beskrivelse = "under 18 år", - regel = EksternRegelId.UNDER_18_AAR, - detaljer = setOf(Opplysning.ER_UNDER_18_AAR, Opplysning.BOSATT_ETTER_FREG_LOVEN) + regel = ApiRegelId.UNDER_18_AAR, + detaljer = listOf(Opplysning.ER_UNDER_18_AAR, Opplysning.BOSATT_ETTER_FREG_LOVEN) ) ) } diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationTestContext.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationTestContext.kt new file mode 100644 index 00000000..94ecc721 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ApplicationTestContext.kt @@ -0,0 +1,166 @@ +package no.nav.paw.arbeidssokerregisteret + +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.registerKotlinModule +import com.nimbusds.jwt.SignedJWT +import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import io.ktor.serialization.jackson.* +import io.mockk.coEvery +import io.mockk.every +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1ArbeidssokerPeriodePutRequest +import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer +import no.nav.paw.arbeidssokerregisteret.domain.NavAnsatt +import no.nav.paw.arbeidssokerregisteret.intern.v1.HarOpplysninger +import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService +import no.nav.paw.arbeidssokerregisteret.services.PersonInfoService +import no.nav.paw.pdl.graphql.generated.enums.Oppholdstillatelse +import no.nav.paw.pdl.graphql.generated.hentperson.* +import no.nav.security.mock.oauth2.MockOAuth2Server +import org.apache.kafka.clients.producer.ProducerRecord + + +fun HttpClientConfig.defaultConfig() { + install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) { + jackson { + registerKotlinModule() + registerModule(JavaTimeModule()) + } + } +} + + +fun MockOAuth2Server.personToken(id: String): SignedJWT = issueToken( + claims = mapOf( + "acr" to "idporten-loa-high", + "pid" to id + ) +) + +fun MockOAuth2Server.ansattToken(navAnsatt: NavAnsatt): SignedJWT = issueToken( + claims = mapOf( + "oid" to navAnsatt.azureId, + "NAVident" to navAnsatt.ident + ) +) + + +fun verify( + actual: ProducerRecord, + expected: ProducerRecord +) { + actual.key() shouldBe expected.key() + val actualValue = actual.value() + val expectedValue = expected.value() + actualValue::class shouldBe expectedValue::class + actualValue.id shouldBe expectedValue.id + actualValue.identitetsnummer shouldBe expectedValue.identitetsnummer + actualValue.metadata.utfoertAv.id shouldBe expectedValue.metadata.utfoertAv.id + actualValue.metadata.utfoertAv.type shouldBe expectedValue.metadata.utfoertAv.type + if (expectedValue is HarOpplysninger) { + actualValue.shouldBeInstanceOf() + actualValue.opplysninger shouldContainExactlyInAnyOrder expectedValue.opplysninger + } +} + +const val bosatt = "bosattEtterFolkeregisterloven" +const val ikkeBosatt = "ikkeBosatt" +const val doed = "doedIFolkeregisteret" +const val forsvunnet = "forsvunnet" +const val opphoert = "opphoert" +const val dNummer = "dNummer" + +val emptyMetadat = Metadata(emptyList()) + +fun String?.innflytting(): List = list().map { + InnflyttingTilNorge( + folkeregistermetadata = Folkeregistermetadata( + gyldighetstidspunkt = it, + ajourholdstidspunkt = it + ) + ) +} + +fun String?.utflytting(): List = list().map { + UtflyttingFraNorge( + utflyttingsdato = it, + folkeregistermetadata = Folkeregistermetadata( + gyldighetstidspunkt = it, + ajourholdstidspunkt = it + ) + ) +} + +fun bostedsadresse( + vegadresse: Vegadresse? = null, + matrikkeladresse: Matrikkeladresse? = null, + utenlandskAdresse: UtenlandskAdresse? = null +): List = listOfNotNull( + if (vegadresse == null && matrikkeladresse == null && utenlandskAdresse == null) null + else { + Bostedsadresse( + vegadresse = vegadresse, + matrikkeladresse = matrikkeladresse, + utenlandskAdresse = utenlandskAdresse, + ) + } +) + +fun String.folkeregisterpersonstatus(): List = + list().map { Folkeregisterpersonstatus(it, emptyMetadat) } + +fun folkeregisterpersonstatus(status: String, vararg statuser: String): List = + (status.list() + statuser).map { Folkeregisterpersonstatus(it, emptyMetadat) } + +fun statsborgerskap(cc: String, vararg ccs: String): List = + (cc.list() + ccs).map { Statsborgerskap(it, emptyMetadat) } + +fun String.statsborgerskap(): List = list().map { Statsborgerskap(it, emptyMetadat) } + +fun A.list(): List = listOfNotNull(this) + +fun Pair?.opphold(): List = list() + .filterNotNull() + .map { + Opphold( + oppholdFra = it.first, + oppholdTil = it.second, + type = if (it.second == null) Oppholdstillatelse.PERMANENT else Oppholdstillatelse.MIDLERTIDIG, + metadata = emptyMetadat + ) + } + +fun AutorisasjonService.setHarTilgangTilBruker(ansatt: NavAnsatt, bruker: String, tilgang: Boolean) { + every { verifiserVeilederTilgangTilBruker(ansatt, Identitetsnummer(bruker)) } returns tilgang +} + +fun PersonInfoService.setPersonInfo(identitetsnummer: String, person: Person?) { + coEvery { + with(any()) { + hentPersonInfo(identitetsnummer) + } + } returns person +} + +suspend fun HttpClient.startPeriode(identitetsnummer: String, token: SignedJWT?, godkjent: Boolean = false): HttpResponse = + put("/api/v1/arbeidssoker/periode") { + token?.also { + bearerAuth(token.serialize()) + } + headers { + append(HttpHeaders.ContentType, ContentType.Application.Json) + } + setBody( + ApiV1ArbeidssokerPeriodePutRequest( + identitetsnummer = identitetsnummer, + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET, + registreringForhaandsGodkjentAvAnsatt = godkjent + ) + ) + } diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngagnSomVeilederTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngagnSomVeilederTest.kt index f6c6af9f..71cc0121 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngagnSomVeilederTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngagnSomVeilederTest.kt @@ -1,5 +1,6 @@ package no.nav.paw.arbeidssokerregisteret +import arrow.core.right import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.registerKotlinModule import io.kotest.core.spec.style.FreeSpec @@ -10,17 +11,22 @@ import io.ktor.http.* import io.ktor.serialization.jackson.* import io.ktor.server.auth.* import io.ktor.server.routing.* -import io.ktor.server.testing.testApplication -import io.mockk.* +import io.ktor.server.testing.* +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1ArbeidssokerPeriodePutRequest +import no.nav.paw.arbeidssokerregisteret.application.OK +import no.nav.paw.arbeidssokerregisteret.application.Regel +import no.nav.paw.arbeidssokerregisteret.application.StartStoppRequestHandler +import no.nav.paw.arbeidssokerregisteret.application.ok +import no.nav.paw.arbeidssokerregisteret.application.regler.AnsattHarTilgangTilBruker import no.nav.paw.arbeidssokerregisteret.auth.configureAuthentication -import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes -import no.nav.security.mock.oauth2.MockOAuth2Server -import no.nav.paw.arbeidssokerregisteret.application.* import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer -import no.nav.paw.arbeidssokerregisteret.domain.http.PeriodeTilstand -import no.nav.paw.arbeidssokerregisteret.domain.http.StartStoppRequest import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization +import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes +import no.nav.security.mock.oauth2.MockOAuth2Server class InngagnSomVeilederTest : FreeSpec({ val oauth = MockOAuth2Server() @@ -42,13 +48,13 @@ class InngagnSomVeilederTest : FreeSpec({ } } returns OK( regel = Regel( - id = RegelId.ANSATT_HAR_TILGANG_TIL_BRUKER, + id = AnsattHarTilgangTilBruker, beskrivelse = "", opplysninger = emptyList(), - vedTreff = ::OK + vedTreff = ::ok ), opplysning = emptySet() - ) + ).right() testApplication { application { configureHTTP() @@ -80,10 +86,10 @@ class InngagnSomVeilederTest : FreeSpec({ headers { append(HttpHeaders.ContentType, ContentType.Application.Json) } - setBody(StartStoppRequest( + setBody(ApiV1ArbeidssokerPeriodePutRequest( identitetsnummer = "12345678909", registreringForhaandsGodkjentAvAnsatt = true, - periodeTilstand = PeriodeTilstand.STARTET + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET )) } response.status shouldBe HttpStatusCode.NoContent @@ -100,10 +106,10 @@ class InngagnSomVeilederTest : FreeSpec({ headers { append(HttpHeaders.ContentType, ContentType.Application.Json) } - setBody(StartStoppRequest( + setBody(ApiV1ArbeidssokerPeriodePutRequest( identitetsnummer = "12345678909", registreringForhaandsGodkjentAvAnsatt = false, - periodeTilstand = PeriodeTilstand.STARTET + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET )) } response2.status shouldBe HttpStatusCode.NoContent @@ -117,4 +123,3 @@ class InngagnSomVeilederTest : FreeSpec({ } } }) - diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngangSomBrukerTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngangSomBrukerTest.kt index ad0596b0..64b55cb2 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngangSomBrukerTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/InngangSomBrukerTest.kt @@ -1,25 +1,26 @@ package no.nav.paw.arbeidssokerregisteret +import arrow.core.left +import arrow.core.right import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.module.kotlin.registerKotlinModule import io.kotest.core.spec.style.FreeSpec import io.kotest.matchers.shouldBe +import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.http.* import io.ktor.serialization.jackson.* -import io.ktor.server.auth.authenticate +import io.ktor.server.auth.* import io.ktor.server.routing.* -import io.ktor.server.testing.testApplication +import io.ktor.server.testing.* import io.mockk.coEvery import io.mockk.coVerify import io.mockk.mockk +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiV1ArbeidssokerPeriodePutRequest import no.nav.paw.arbeidssokerregisteret.application.* -import no.nav.paw.arbeidssokerregisteret.application.OK +import no.nav.paw.arbeidssokerregisteret.application.regler.IkkeAnsattOgForhaandsgodkjentAvAnsatt import no.nav.paw.arbeidssokerregisteret.auth.configureAuthentication import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer -import no.nav.paw.arbeidssokerregisteret.domain.http.PeriodeTilstand -import no.nav.paw.arbeidssokerregisteret.domain.http.StartStoppRequest import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes @@ -45,13 +46,14 @@ class InngangSomBrukerTest : FreeSpec({ } } returns OK( regel = Regel( - id = RegelId.OVER_18_AAR_OG_BOSATT_ETTER_FREG_LOVEN, + id = Over18AarOgBosattEtterFregLoven, beskrivelse = "", opplysninger = emptyList(), - vedTreff = ::OK + vedTreff = ::ok ), opplysning = emptySet() - ) + ).right() + testApplication { application { configureHTTP() @@ -81,10 +83,10 @@ class InngangSomBrukerTest : FreeSpec({ bearerAuth(token.serialize()) headers { append(HttpHeaders.ContentType, ContentType.Application.Json) } setBody( - StartStoppRequest( + ApiV1ArbeidssokerPeriodePutRequest( identitetsnummer = "12345678909", registreringForhaandsGodkjentAvAnsatt = false, - periodeTilstand = PeriodeTilstand.STARTET + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET ) ) } @@ -98,21 +100,21 @@ class InngangSomBrukerTest : FreeSpec({ } - "Bruker som har forhandsgodkjentflagg aktivt" - { + "Bruker som har forhandsgodkjentflagg aktivt" { val startStoppRequestHandler: StartStoppRequestHandler = mockk() coEvery { with(any()) { startStoppRequestHandler.startArbeidssokerperiode(any(), any()) } - } returns UgyldigRequestBasertPaaAutentisering( + } returns Problem( regel = Regel( - id = RegelId.IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT, + id = IkkeAnsattOgForhaandsgodkjentAvAnsatt, beskrivelse = "", opplysninger = emptyList(), - vedTreff = ::UgyldigRequestBasertPaaAutentisering + vedTreff = ::problem ), opplysning = emptySet() - ) + ).left() testApplication { application { configureHTTP() @@ -142,10 +144,10 @@ class InngangSomBrukerTest : FreeSpec({ bearerAuth(token.serialize()) headers { append(HttpHeaders.ContentType, ContentType.Application.Json) } setBody( - StartStoppRequest( + ApiV1ArbeidssokerPeriodePutRequest( identitetsnummer = "12345678909", registreringForhaandsGodkjentAvAnsatt = false, - periodeTilstand = PeriodeTilstand.STARTET + periodeTilstand = ApiV1ArbeidssokerPeriodePutRequest.PeriodeTilstand.STARTET ) ) } diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt new file mode 100644 index 00000000..d83f3c0c --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/ProducerMock.kt @@ -0,0 +1,74 @@ +package no.nav.paw.arbeidssokerregisteret + +import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import org.apache.kafka.clients.consumer.ConsumerGroupMetadata +import org.apache.kafka.clients.consumer.OffsetAndMetadata +import org.apache.kafka.clients.producer.Callback +import org.apache.kafka.clients.producer.Producer +import org.apache.kafka.clients.producer.ProducerRecord +import org.apache.kafka.clients.producer.RecordMetadata +import org.apache.kafka.common.* +import java.time.Duration +import java.time.Instant +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Future +import java.util.concurrent.LinkedBlockingQueue + +class ProducerMock : Producer { + private val queue = LinkedBlockingQueue>(100) + fun next(): ProducerRecord = queue.take() + + override fun close() {} + + override fun close(timeout: Duration?) {} + + override fun initTransactions() {} + + override fun beginTransaction() {} + + override fun sendOffsetsToTransaction( + offsets: MutableMap?, + consumerGroupId: String? + ) { + } + + override fun sendOffsetsToTransaction( + offsets: MutableMap?, + groupMetadata: ConsumerGroupMetadata? + ) { + } + + override fun commitTransaction() {} + + override fun abortTransaction() {} + + override fun flush() {} + + override fun partitionsFor(topic: String?): MutableList { + TODO("Not yet implemented") + } + + override fun metrics(): MutableMap { + return mutableMapOf() + } + + override fun clientInstanceId(timeout: Duration?): Uuid { + return Uuid.ZERO_UUID + } + + override fun send(record: ProducerRecord?, callback: Callback): Future { + queue.put(record) + val metedata = RecordMetadata( + TopicPartition(record!!.topic(), 0), + 1L, 0, Instant.now().toEpochMilli(), 3, 3 + ) + val result = CompletableFuture.completedFuture(metedata) + callback.onCompletion(metedata, null) + return result + } + + override fun send(record: ProducerRecord?): Future { + TODO("Not yet implemented") + } + +} diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TestCaseRunner.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TestCaseRunner.kt new file mode 100644 index 00000000..4a1e2308 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TestCaseRunner.kt @@ -0,0 +1,117 @@ +package no.nav.paw.arbeidssokerregisteret + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder +import io.kotest.matchers.collections.shouldNotBeEmpty +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.ktor.client.call.* +import io.ktor.server.auth.* +import io.ktor.server.testing.* +import io.mockk.mockk +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.application.RequestValidator +import no.nav.paw.arbeidssokerregisteret.application.StartStoppRequestHandler +import no.nav.paw.arbeidssokerregisteret.auth.configureAuthentication +import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import no.nav.paw.arbeidssokerregisteret.plugins.configureHTTP +import no.nav.paw.arbeidssokerregisteret.plugins.configureSerialization +import no.nav.paw.arbeidssokerregisteret.routes.arbeidssokerRoutes +import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService +import no.nav.paw.arbeidssokerregisteret.services.PersonInfoService +import no.nav.paw.arbeidssokerregisteret.testdata.TestCase +import no.nav.paw.arbeidssokerregisteret.testdata.TestCaseBuilder +import no.nav.paw.kafkakeygenerator.client.inMemoryKafkaKeysMock +import no.nav.security.mock.oauth2.MockOAuth2Server +import org.slf4j.LoggerFactory + +class TestCaseRunner : FreeSpec({ + val mockOAuthServer = MockOAuth2Server() + beforeSpec { + mockOAuthServer.start() + } + afterSpec { + mockOAuthServer.shutdown() + } + val testCases = TestCase::class.sealedSubclasses + "Verifiserer oppsett av test caser" - { + "Det må finnes minst en test" { + testCases.shouldNotBeEmpty() + } + "Alle tester må ha 'objectInstance" - { + testCases.forEach { case -> + "${case.simpleName} må ha 'objectInstance'" { + case.objectInstance.shouldNotBeNull() + } + } + } + } + "Test cases" - { + TestCase::class.sealedSubclasses + .mapNotNull { it.objectInstance } + .forEach { testCase -> + val logger = LoggerFactory.getLogger(testCase::class.java) + "Test ${testCase::class.simpleName?.readable()}" { + testApplication { + application { + configureSerialization() + configureHTTP() + configureAuthentication(mockOAuthServer) + } + val autorisasjonService = mockk() + val personInfoService = mockk() + val producer: ProducerMock = ProducerMock() + val kafkaKeys = inMemoryKafkaKeysMock() + val startStoppRequestHandler = StartStoppRequestHandler( + hendelseTopic = "any", + requestValidator = RequestValidator( + autorisasjonService = autorisasjonService, + personInfoService = personInfoService + ), + producer = producer, + kafkaKeysClient = kafkaKeys + ) + routing { + authenticate("tokenx", "azure") { + arbeidssokerRoutes(startStoppRequestHandler, mockk()) + } + } + val client = createClient { defaultConfig() } + val id = testCase.id + val person = testCase.person + logger.info("Running test for $id") + personInfoService.setPersonInfo(id, person) + val testConfiguration = TestCaseBuilder(mockOAuthServer, autorisasjonService) + .also { testCase.configure(it) } + val status = client.startPeriode(id, testConfiguration.authToken, testCase.forhaandsGodkjent) + status.status shouldBe testCase.producesHttpResponse + testCase.producesError?.also { expectedErrorResponse -> + val body = status.body() + body.feilKode shouldBe expectedErrorResponse.feilKode + body.aarsakTilAvvisning?.regel shouldBe expectedErrorResponse.aarsakTilAvvisning?.regel + expectedErrorResponse.aarsakTilAvvisning?.detaljer?.also { expectedDetails -> + body.aarsakTilAvvisning?.detaljer.shouldNotBeNull() + body.aarsakTilAvvisning?.detaljer?.shouldContainExactlyInAnyOrder(expectedDetails) + } + } + val expectedRecord = testCase.producesRecord(kafkaKeys) + if (expectedRecord != null) { + verify( + actual = producer.next(), + expected = expectedRecord + ) + } else { + producer.next().shouldBeNull() + } + } + } + } + } +}) + +fun String.readable(): String = + map { letter -> if (letter.isUpperCase()) " ${letter.lowercase()}" else "$letter" } + .joinToString("") + .replace("oe", "ø") + .replace("aa", "å") diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TilgansReglerTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TilgansReglerTest.kt index b728e0fb..f379cb86 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TilgansReglerTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/TilgansReglerTest.kt @@ -1,32 +1,39 @@ package no.nav.paw.arbeidssokerregisteret +import arrow.core.Either import io.kotest.core.spec.style.FreeSpec -import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.collections.shouldContainAll import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf import no.nav.paw.arbeidssokerregisteret.application.* +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.AnsattTilgang +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.IkkeAnsatt +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning +import no.nav.paw.arbeidssokerregisteret.application.regler.AnsattHarTilgangTilBruker +import no.nav.paw.arbeidssokerregisteret.application.regler.IkkeAnsattOgForhaandsgodkjentAvAnsatt import no.nav.paw.arbeidssokerregisteret.application.regler.tilgangsReglerIPrioritertRekkefolge -import no.nav.paw.arbeidssokerregisteret.services.PersonInfoService -import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel -import no.nav.paw.pdl.graphql.generated.hentperson.Person class TilgansReglerTest : FreeSpec({ "eval av tilgang skal gi" - { "ugydlig request ved IKKE_ANSATT kombinert med GODKJENT_AV_ANSATT" { - tilgangsReglerIPrioritertRekkefolge.evaluer( + val resultat = tilgangsReglerIPrioritertRekkefolge.evaluer( setOf( - Opplysning.IKKE_ANSATT, - Opplysning.FORHAANDSGODKJENT_AV_ANSATT + IkkeAnsatt, + DomeneOpplysning.ErForhaandsgodkjent ) - ).shouldBeInstanceOf() + ).shouldBeInstanceOf>() + resultat.value.regel.id shouldBe IkkeAnsattOgForhaandsgodkjentAvAnsatt + resultat.value.opplysning shouldContainAll listOf(IkkeAnsatt, DomeneOpplysning.ErForhaandsgodkjent) } "lovlig kombinasjon av ANSATT og FORHANDSGODKJENT_AV_ANSATT" { - tilgangsReglerIPrioritertRekkefolge.evaluer( + val resultat = tilgangsReglerIPrioritertRekkefolge.evaluer( setOf( - Opplysning.ANSATT_TILGANG, - Opplysning.FORHAANDSGODKJENT_AV_ANSATT + AnsattTilgang, + DomeneOpplysning.ErForhaandsgodkjent ) - ).shouldBeInstanceOf() + ).shouldBeInstanceOf>() + resultat.value.regel.id shouldBe AnsattHarTilgangTilBruker + resultat.value.opplysning shouldContainAll listOf(AnsattTilgang, DomeneOpplysning.ErForhaandsgodkjent) } } } diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EksternRegelIdTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EksternRegelIdTest.kt index a8b88e88..6f2b9ba4 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EksternRegelIdTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EksternRegelIdTest.kt @@ -2,14 +2,12 @@ package no.nav.paw.arbeidssokerregisteret.application import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe +import no.nav.paw.arbeidssokerregisteret.application.regler.AuthRegelId class EksternRegelIdTest: FunSpec({ test("verifiser at alle eksterne regler matcher en intern regel") { - EksternRegelId.entries - .filter { it != EksternRegelId.UKJENT_REGEL } - .forEach {eksternRegelId -> - val internRegelId = RegelId.valueOf(eksternRegelId.name) - eksternRegelId shouldBe internRegelId.eksternRegelId - } + val domeneRegelIder = DomeneRegelId::class.nestedClasses + val authRegelIder = AuthRegelId::class.nestedClasses + } }) diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensionsKtTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensionsKtTest.kt new file mode 100644 index 00000000..300440dc --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensionsKtTest.kt @@ -0,0 +1,35 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning as HendelseOpplysning + +class RegelExtensionsKtTest : FreeSpec({ + "Alle opplysninger kan konverteres til hendelse-opplysning" - { + val domeneOpplysninger = DomeneOpplysning::class.sealedSubclasses.mapNotNull { it.objectInstance }.map { it as Opplysning } + val authOpplysninger = AuthOpplysning::class.sealedSubclasses.mapNotNull { it.objectInstance }.map { it as Opplysning } + val hendelseOpplysninger = (domeneOpplysninger + authOpplysninger).map { + mapToHendelseOpplysning(it) + .also { res -> + "$it skal ikke mappes til ${HendelseOpplysning.UKJENT_OPPLYSNING}" { + res.shouldNotBe(HendelseOpplysning.UKJENT_OPPLYSNING) + } + } + } + val forventedHendelseOpplysninger = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.entries + .filter { it != HendelseOpplysning.UKJENT_OPPLYSNING } + forventedHendelseOpplysninger.forEach { forventetHendelseOpplysning -> + "$forventetHendelseOpplysning skal være i resultatet" { + hendelseOpplysninger shouldContain forventetHendelseOpplysning + } + } + "resultatet skal inneholde ${hendelseOpplysninger.toSet().size} unike opplysninger" { + forventedHendelseOpplysninger.toSet() shouldBe hendelseOpplysninger.toSet() + } + } +}) \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidatorTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidatorTest.kt index 08239f39..35f168b1 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidatorTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/RequestValidatorTest.kt @@ -1,12 +1,19 @@ package no.nav.paw.arbeidssokerregisteret.application +import arrow.core.Either import io.kotest.core.spec.style.FreeSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.collections.shouldNotContain import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf import io.mockk.coEvery import io.mockk.mockk import no.nav.paw.arbeidssokerregisteret.RequestScope +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.AnsattIkkeTilgang +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.AnsattTilgang +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.IkkeAnsatt +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.* +import no.nav.paw.arbeidssokerregisteret.application.regler.IkkeAnsattOgForhaandsgodkjentAvAnsatt import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService import no.nav.paw.arbeidssokerregisteret.services.PersonInfoService @@ -40,22 +47,22 @@ class RequestValidatorTest : FreeSpec({ autorisasjonService.verifiserVeilederTilgangTilBruker(any(), any()) } returns true val requestValidator = RequestValidator(autorisasjonService, personInfoService) - "Når forhandsgodkjent av veileder er false" - { + "Når forhandsgodkjent av veileder er false" { val tilgangskontrollresultat = with(requestScope) { requestValidator.validerTilgang(identitsnummer) - } - tilgangskontrollresultat.opplysning shouldContain Opplysning.ANSATT_TILGANG - tilgangskontrollresultat.opplysning shouldNotContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT + }.shouldBeInstanceOf>() + tilgangskontrollresultat.value.opplysning shouldContain AnsattTilgang + tilgangskontrollresultat.value.opplysning shouldNotContain DomeneOpplysning.ErForhaandsgodkjent } - "Når forhandsgodkjent av ansatt er true" - { + "Når forhandsgodkjent av ansatt er true" { val tilgangskontrollresultat = with(requestScope) { requestValidator.validerTilgang(identitsnummer, true) - } - tilgangskontrollresultat.opplysning shouldContain Opplysning.ANSATT_TILGANG - tilgangskontrollresultat.opplysning shouldContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT + }.shouldBeInstanceOf>() + tilgangskontrollresultat.value.opplysning shouldContain AnsattTilgang + tilgangskontrollresultat.value.opplysning shouldContain DomeneOpplysning.ErForhaandsgodkjent } } - "Når veileder ikke har tilgang til bruker" - { + "Når veileder ikke har tilgang til bruker" { val autorisasjonService: AutorisasjonService = mockk() coEvery { autorisasjonService.verifiserVeilederTilgangTilBruker(any(), any()) @@ -64,8 +71,8 @@ class RequestValidatorTest : FreeSpec({ val tilgangskontrollresultat = with(requestScope) { requestValidator.validerTilgang(identitsnummer) - } - tilgangskontrollresultat.opplysning shouldContain Opplysning.ANSATT_IKKE_TILGANG + }.shouldBeInstanceOf>() + tilgangskontrollresultat.value.opplysning shouldContain AnsattIkkeTilgang } } "Når bruker er logget inn" - { @@ -79,20 +86,20 @@ class RequestValidatorTest : FreeSpec({ ) val autorisasjonService: AutorisasjonService = mockk() val requestValidator = RequestValidator(autorisasjonService, personInfoService) - "standardbruker" - { + "standardbruker" { val tilgangskontrollresultat = with(requestScope) { requestValidator.validerTilgang(identitsnummer) - } - tilgangskontrollresultat.opplysning shouldContain Opplysning.IKKE_ANSATT - tilgangskontrollresultat.opplysning shouldNotContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT + }.shouldBeInstanceOf>() + tilgangskontrollresultat.value.opplysning shouldContain IkkeAnsatt + tilgangskontrollresultat.value.opplysning shouldNotContain DomeneOpplysning.ErForhaandsgodkjent } - "forhåndsgodkjentflagg" - { + "forhåndsgodkjentflagg" { val tilgangskontrollresultat = with(requestScope) { requestValidator.validerTilgang(identitsnummer, true) - } - tilgangskontrollresultat.opplysning shouldContain Opplysning.IKKE_ANSATT - tilgangskontrollresultat.opplysning shouldContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT - tilgangskontrollresultat.regel.id.shouldBe(RegelId.IKKE_ANSATT_OG_FORHAANDSGODKJENT_AV_ANSATT) + }.shouldBeInstanceOf>() + tilgangskontrollresultat.value.opplysning shouldContain IkkeAnsatt + tilgangskontrollresultat.value.opplysning shouldContain DomeneOpplysning.ErForhaandsgodkjent + tilgangskontrollresultat.value.regel.id.shouldBe(IkkeAnsattOgForhaandsgodkjentAvAnsatt) } } @@ -129,26 +136,27 @@ class RequestValidatorTest : FreeSpec({ ), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) - "godkjent av veilederflagg er true" - { + "godkjent av veilederflagg er true" { val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer, true) - } - resultat.opplysning shouldContain Opplysning.IKKE_ANSATT - resultat.opplysning shouldContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain IkkeAnsatt + resultat.value.opplysning shouldContain DomeneOpplysning.ErForhaandsgodkjent } - "godkjent av veileder er false" - { + "godkjent av veileder er false" { val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.IKKE_ANSATT - resultat.opplysning shouldNotContain Opplysning.FORHAANDSGODKJENT_AV_ANSATT + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain IkkeAnsatt + resultat.value.opplysning shouldNotContain DomeneOpplysning.ErForhaandsgodkjent } } - "Bruker ikke bosatt" - { + "Bruker ikke bosatt" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -174,15 +182,16 @@ class RequestValidatorTest : FreeSpec({ ), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.IKKE_BOSATT - + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.IkkeBosatt + resultat.value.regel.id shouldBe IkkeBosattINorgeIHenholdTilFolkeregisterloven } - "Bruker har dNummer" - { + "Bruker har dNummer" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -214,15 +223,17 @@ class RequestValidatorTest : FreeSpec({ ), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.IKKE_BOSATT - resultat.opplysning shouldContain Opplysning.DNUMMER + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.IkkeBosatt + resultat.value.opplysning shouldContain DomeneOpplysning.Dnummer + resultat.value.regel.id shouldBe IkkeBosattINorgeIHenholdTilFolkeregisterloven } - "Person ikke funnet" - { + "Person ikke funnet" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -238,10 +249,11 @@ class RequestValidatorTest : FreeSpec({ } returns null val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.PERSON_IKKE_FUNNET + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.PersonIkkeFunnet + resultat.value.regel.id shouldBe IkkeFunnet } - "Ukjent alder" - { + "Ukjent alder" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -260,14 +272,15 @@ class RequestValidatorTest : FreeSpec({ folkeregisterpersonstatus = emptyList(), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.UKJENT_FOEDSELSDATO + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.UkjentFoedselsdato } - "Registrert som død" - { + "Registrert som død" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -293,14 +306,15 @@ class RequestValidatorTest : FreeSpec({ ), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.DOED + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.ErDoed } - "Registrert som savnet" - { + "Registrert som savnet" { val requestScope = RequestScope( claims = ResolvedClaims() .add(TokenXPID, "12345678909"), @@ -332,12 +346,13 @@ class RequestValidatorTest : FreeSpec({ ), opphold = emptyList(), innflyttingTilNorge = emptyList(), - utflyttingFraNorge = emptyList() + utflyttingFraNorge = emptyList(), + statsborgerskap = listOf(Statsborgerskap("ARG", Metadata(emptyList()))) ) val resultat = with(requestScope) { requestValidator.validerStartAvPeriodeOenske(identitsnummer) - } - resultat.opplysning shouldContain Opplysning.SAVNET + }.shouldBeInstanceOf>() + resultat.value.opplysning shouldContain DomeneOpplysning.ErSavnet } } diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/services/AutorisasjonServiceTest.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/services/AutorisasjonServiceTest.kt index d5d14977..d9f9cde8 100644 --- a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/services/AutorisasjonServiceTest.kt +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/services/AutorisasjonServiceTest.kt @@ -1,14 +1,13 @@ package no.nav.paw.arbeidssokerregisteret.services import io.kotest.core.spec.style.FreeSpec -import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk import no.nav.paw.arbeidssokerregisteret.RequestScope import no.nav.paw.arbeidssokerregisteret.TestData -import no.nav.paw.arbeidssokerregisteret.application.Opplysning -import no.nav.paw.arbeidssokerregisteret.application.fakta.navAnsattTilgangFakta +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.AuthOpplysning.IkkeAnsatt +import no.nav.paw.arbeidssokerregisteret.application.authfaktka.navAnsattTilgangFakta import no.nav.paw.arbeidssokerregisteret.domain.Identitetsnummer import no.nav.paw.arbeidssokerregisteret.utils.ResolvedClaims import no.nav.paw.arbeidssokerregisteret.utils.TokenXPID @@ -65,7 +64,7 @@ class AutorisasjonServiceTest : FreeSpec({ path = "test" ) with (requestScope) { - autorisasjonService.navAnsattTilgangFakta(identitet) shouldBe Opplysning.IKKE_ANSATT + autorisasjonService.navAnsattTilgangFakta(identitet) shouldBe IkkeAnsatt } } }) diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattMedForhaandgodkjenning.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattMedForhaandgodkjenning.kt new file mode 100644 index 00000000..13d8f57d --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattMedForhaandgodkjenning.kt @@ -0,0 +1,78 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.AarsakTilAvvisning +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiRegelId +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.* +import no.nav.paw.arbeidssokerregisteret.domain.NavAnsatt +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.Startet +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.paw.pdl.graphql.generated.hentperson.Vegadresse +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Opplysning as ApiOpplysning + +data object AnsattRegistrererIkkeEuEoesBrukerIkkeBosattMedForhaandgodkjenning: TestCase { + override val id = "12345678906" + override val forhaandsGodkjent: Boolean = true + override val person = Person( + foedsel = Foedsel("2000-03-04", 2000).list(), + statsborgerskap = "AFG".statsborgerskap(), + opphold = ("2018-01-01" to null).opphold(), + folkeregisterpersonstatus = dNummer.folkeregisterpersonstatus(), + bostedsadresse = bostedsadresse( + vegadresse = Vegadresse("1201") + ), + innflyttingTilNorge = "2018-01-02T13:23:12".innflytting(), + utflyttingFraNorge = "2017-01-02".utflytting() + ) + private val ansatt = NavAnsatt(UUID.randomUUID(), UUID.randomUUID().toString()) + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.ansattToken(ansatt) + autorisasjonService.setHarTilgangTilBruker(ansatt, id, true) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.NoContent + override val producesError: Feil? = null + + override fun producesRecord( + kafkaKeysClient: KafkaKeysClient + ) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Startet( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = ansatt.ident, + type = BrukerType.VEILEDER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.ER_OVER_18_AAR, + Opplysning.HAR_NORSK_ADRESSE, + Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + Opplysning.ANSATT_TILGANG, + Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE, + Opplysning.DNUMMER, + Opplysning.TOKENX_PID_IKKE_FUNNET, + Opplysning.FORHAANDSGODKJENT_AV_ANSATT + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.kt new file mode 100644 index 00000000..c586473e --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.kt @@ -0,0 +1,91 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.AarsakTilAvvisning +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiRegelId +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.* +import no.nav.paw.arbeidssokerregisteret.domain.NavAnsatt +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.paw.pdl.graphql.generated.hentperson.Vegadresse +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Opplysning as ApiOpplysning + +data object AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning: TestCase { + override val id = "12345678906" + override val person = Person( + foedsel = Foedsel("2000-03-04", 2000).list(), + statsborgerskap = "AFG".statsborgerskap(), + opphold = ("2018-01-01" to null).opphold(), + folkeregisterpersonstatus = dNummer.folkeregisterpersonstatus(), + bostedsadresse = bostedsadresse( + vegadresse = Vegadresse("1201") + ), + innflyttingTilNorge = "2018-01-02T13:23:12".innflytting(), + utflyttingFraNorge = "2017-01-02".utflytting() + ) + private val ansatt = NavAnsatt(UUID.randomUUID(), UUID.randomUUID().toString()) + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.ansattToken(ansatt) + autorisasjonService.setHarTilgangTilBruker(ansatt, id, true) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.Forbidden + override val producesError: Feil = Feil( + melding = "any", + feilKode = Feil.FeilKode.AVVIST, + aarsakTilAvvisning = AarsakTilAvvisning( + beskrivelse = "any", + regel = ApiRegelId.IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN, + detaljer = listOf( + ApiOpplysning.ER_OVER_18_AAR, + ApiOpplysning.HAR_NORSK_ADRESSE, + ApiOpplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + ApiOpplysning.ANSATT_TILGANG, + ApiOpplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE, + ApiOpplysning.DNUMMER, + ApiOpplysning.TOKENX_PID_IKKE_FUNNET + ) + ) + ) + + override fun producesRecord( + kafkaKeysClient: KafkaKeysClient + ) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Avvist( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = ansatt.ident, + type = BrukerType.VEILEDER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.ER_OVER_18_AAR, + Opplysning.HAR_NORSK_ADRESSE, + Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + Opplysning.ANSATT_TILGANG, + Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE, + Opplysning.DNUMMER, + Opplysning.TOKENX_PID_IKKE_FUNNET + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererUtenTilgangTilBruker.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererUtenTilgangTilBruker.kt new file mode 100644 index 00000000..589bab58 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/AnsattRegistrererUtenTilgangTilBruker.kt @@ -0,0 +1,71 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.* +import no.nav.paw.arbeidssokerregisteret.domain.NavAnsatt +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.paw.pdl.graphql.generated.hentperson.Vegadresse +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* + +data object AnsattRegistrererUtenTilgangTilBruker: TestCase { + override val id = "12345678906" + override val person = Person( + foedsel = Foedsel("2000-03-04", 2000).list(), + statsborgerskap = "AFG".statsborgerskap(), + opphold = ("2018-01-01" to null).opphold(), + folkeregisterpersonstatus = dNummer.folkeregisterpersonstatus(), + bostedsadresse = bostedsadresse( + vegadresse = Vegadresse("1201") + ), + innflyttingTilNorge = "2018-01-02T13:23:12".innflytting(), + utflyttingFraNorge = "2017-01-02".utflytting() + ) + private val ansatt = NavAnsatt(UUID.randomUUID(), UUID.randomUUID().toString()) + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.ansattToken(ansatt) + autorisasjonService.setHarTilgangTilBruker(ansatt, id, false) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.Forbidden + override val producesError: Feil = Feil( + melding = "any", + feilKode = Feil.FeilKode.IKKE_TILGANG, + aarsakTilAvvisning = null + ) + + override fun producesRecord(kafkaKeysClient: KafkaKeysClient) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.id).key }, + Avvist( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey( + AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.id + ).id }, + identitetsnummer = AnsattRegistrererIkkeEuEoesBrukerIkkeBosattUtenForhaandgodkjenning.id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = ansatt.ident, + type = BrukerType.VEILEDER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.ANSATT_IKKE_TILGANG, + Opplysning.TOKENX_PID_IKKE_FUNNET + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/HentPersonReturnererNull.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/HentPersonReturnererNull.kt new file mode 100644 index 00000000..496f9ed2 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/HentPersonReturnererNull.kt @@ -0,0 +1,68 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.AarsakTilAvvisning +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiRegelId +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Opplysning +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning.* +import no.nav.paw.arbeidssokerregisteret.personToken +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* + +data object HentPersonReturnererNull: TestCase { + override val id = "12345678909" + override val person = null + + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.personToken(id) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.Forbidden + override val producesError: Feil = Feil( + melding = "any", + feilKode = Feil.FeilKode.AVVIST, + aarsakTilAvvisning = AarsakTilAvvisning( + beskrivelse = "any", + regel = ApiRegelId.IKKE_FUNNET, + detaljer = listOf( + Opplysning.PERSON_IKKE_FUNNET, + Opplysning.SAMME_SOM_INNLOGGET_BRUKER, + Opplysning.IKKE_ANSATT + ) + ) + ) + + override fun producesRecord( + kafkaKeysClient: KafkaKeysClient + ) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Avvist( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = id, + type = BrukerType.SLUTTBRUKER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + SAMME_SOM_INNLOGGET_BRUKER, + PERSON_IKKE_FUNNET, + IKKE_ANSATT + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/IkkeEuEoesBrukerIkkeBosatt.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/IkkeEuEoesBrukerIkkeBosatt.kt new file mode 100644 index 00000000..ed80f192 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/IkkeEuEoesBrukerIkkeBosatt.kt @@ -0,0 +1,89 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.AarsakTilAvvisning +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.ApiRegelId +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.* +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.paw.pdl.graphql.generated.hentperson.Vegadresse +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Opplysning as ApiOpplysning + +data object IkkeEuEoesBrukerIkkeBosatt: TestCase { + override val id = "12345678919" + override val person = Person( + foedsel = Foedsel("2000-03-04", 2000).list(), + statsborgerskap = "AFG".statsborgerskap(), + opphold = ("2018-01-01" to null).opphold(), + folkeregisterpersonstatus = dNummer.folkeregisterpersonstatus(), + bostedsadresse = bostedsadresse( + vegadresse = Vegadresse("1201") + ), + innflyttingTilNorge = "2018-01-02T13:23:12".innflytting(), + utflyttingFraNorge = "2017-01-02".utflytting() + ) + + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.personToken(id) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.Forbidden + override val producesError: Feil = Feil( + melding = "any", + feilKode = Feil.FeilKode.AVVIST, + aarsakTilAvvisning = AarsakTilAvvisning( + beskrivelse = "any", + regel = ApiRegelId.IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN, + detaljer = listOf( + ApiOpplysning.ER_OVER_18_AAR, + ApiOpplysning.HAR_NORSK_ADRESSE, + ApiOpplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + ApiOpplysning.IKKE_ANSATT, + ApiOpplysning.SAMME_SOM_INNLOGGET_BRUKER, + ApiOpplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE, + ApiOpplysning.DNUMMER + ) + ) + ) + + override fun producesRecord( + kafkaKeysClient: KafkaKeysClient + ) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Avvist( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = id, + type = BrukerType.SLUTTBRUKER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.ER_OVER_18_AAR, + Opplysning.HAR_NORSK_ADRESSE, + Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + Opplysning.IKKE_ANSATT, + Opplysning.SAMME_SOM_INNLOGGET_BRUKER, + Opplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE, + Opplysning.DNUMMER + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/NorskBrukerBosattINorge.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/NorskBrukerBosattINorge.kt new file mode 100644 index 00000000..34e83e0a --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/NorskBrukerBosattINorge.kt @@ -0,0 +1,71 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.* +import no.nav.paw.arbeidssokerregisteret.intern.v1.Startet +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.paw.pdl.graphql.generated.hentperson.Vegadresse +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* + +data object NorskBrukerBosattINorge: TestCase { + override val id = "12345678909" + override val person = Person( + foedsel = Foedsel("2000-03-04", 2000).list(), + statsborgerskap = "NOR".statsborgerskap(), + opphold = emptyList(), + folkeregisterpersonstatus = bosatt.folkeregisterpersonstatus(), + bostedsadresse = bostedsadresse( + vegadresse = Vegadresse("1201") + ), + innflyttingTilNorge = "2018-01-02T13:23:12".innflytting(), + utflyttingFraNorge = "2017-01-02".utflytting() + ) + + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.personToken(id) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.NoContent + override val producesError: Feil? = null + + override fun producesRecord( + kafkaKeysClient: KafkaKeysClient + ) = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Startet( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = id, + type = BrukerType.SLUTTBRUKER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.ER_OVER_18_AAR, + Opplysning.BOSATT_ETTER_FREG_LOVEN, + Opplysning.ER_EU_EOES_STATSBORGER, + Opplysning.HAR_NORSK_ADRESSE, + Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE, + Opplysning.IKKE_ANSATT, + Opplysning.SAMME_SOM_INNLOGGET_BRUKER, + Opplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/SluttbrukerProeverAaEndreForAnnenPerson.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/SluttbrukerProeverAaEndreForAnnenPerson.kt new file mode 100644 index 00000000..e7184030 --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/SluttbrukerProeverAaEndreForAnnenPerson.kt @@ -0,0 +1,66 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import io.kotest.common.runBlocking +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist +import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Bruker +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.BrukerType +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning +import no.nav.paw.arbeidssokerregisteret.personToken +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import org.apache.kafka.clients.producer.ProducerRecord +import java.time.Instant +import java.util.* + +data object SluttbrukerProeverAaEndreForAnnenPerson : TestCase { + override val id: String = "09876543211" + override val person: Person = Person( + foedsel = emptyList(), + statsborgerskap = emptyList(), + opphold = emptyList(), + folkeregisterpersonstatus = emptyList(), + bostedsadresse = emptyList(), + innflyttingTilNorge = emptyList(), + utflyttingFraNorge = emptyList() + ) + private val autentiserBruker = "1234567890" + override val configure: TestCaseBuilder.() -> Unit = { + authToken = mockOAuth2Server.personToken(autentiserBruker) + } + + override val producesHttpResponse: HttpStatusCode = HttpStatusCode.Forbidden + override val producesError: Feil + get() = Feil( + melding = "any", + feilKode = Feil.FeilKode.IKKE_TILGANG, + aarsakTilAvvisning = null + ) + + override fun producesRecord(kafkaKeysClient: KafkaKeysClient): ProducerRecord = ProducerRecord( + "any", + runBlocking { kafkaKeysClient.getIdAndKey(id).key }, + Avvist( + hendelseId = UUID.randomUUID(), + id = runBlocking { kafkaKeysClient.getIdAndKey(id).id }, + identitetsnummer = id, + metadata = Metadata( + tidspunkt = Instant.now(), + kilde = "paw-arbeidssokerregisteret-api-start-stopp-perioder", + utfoertAv = Bruker( + id = autentiserBruker, + type = BrukerType.SLUTTBRUKER + ), + aarsak = "any", + tidspunktFraKilde = null + ), + opplysninger = setOf( + Opplysning.IKKE_SAMME_SOM_INNLOGGER_BRUKER, + Opplysning.IKKE_ANSATT + ) + ) + ) +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/TestCase.kt b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/TestCase.kt new file mode 100644 index 00000000..7c1f98df --- /dev/null +++ b/apps/api-start-stopp-perioder/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/testdata/TestCase.kt @@ -0,0 +1,28 @@ +package no.nav.paw.arbeidssokerregisteret.testdata + +import com.nimbusds.jwt.SignedJWT +import io.ktor.http.* +import no.nav.paw.arbeidssoekerregisteret.api.startstopp.models.Feil +import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import no.nav.paw.arbeidssokerregisteret.services.AutorisasjonService +import no.nav.paw.kafkakeygenerator.client.KafkaKeysClient +import no.nav.paw.pdl.graphql.generated.hentperson.Person +import no.nav.security.mock.oauth2.MockOAuth2Server +import org.apache.kafka.clients.producer.ProducerRecord + +sealed interface TestCase { + val forhaandsGodkjent: Boolean get() = false + val id: String + val person: Person? + val configure: TestCaseBuilder.() -> Unit + val producesHttpResponse: HttpStatusCode + val producesError: Feil? + fun producesRecord(kafkaKeysClient: KafkaKeysClient): ProducerRecord? +} + +class TestCaseBuilder( + val mockOAuth2Server: MockOAuth2Server, + val autorisasjonService: AutorisasjonService +) { + var authToken: SignedJWT? = null +} \ No newline at end of file diff --git a/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/Topology.kt b/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/Topology.kt index 282a365f..d53b0a2a 100644 --- a/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/Topology.kt +++ b/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/Topology.kt @@ -3,8 +3,8 @@ package no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka import io.micrometer.prometheusmetrics.PrometheusMeterRegistry import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.clients.pdl.PdlHentForenkletStatus import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.processors.oppdaterHendelseState -import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.serdes.HendelseSerde import no.nav.paw.arbeidssokerregisteret.api.v1.Periode +import no.nav.paw.arbeidssokerregisteret.intern.v1.HendelseSerde import no.nav.paw.arbeidssokerregisteret.intern.v1.Startet import org.apache.kafka.common.serialization.Serdes import org.apache.kafka.streams.StreamsBuilder diff --git a/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/serdes/HendelseSerde.kt b/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/serdes/HendelseSerde.kt deleted file mode 100644 index b64e8ead..00000000 --- a/apps/utgang-pdl/src/main/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/kafka/serdes/HendelseSerde.kt +++ /dev/null @@ -1,69 +0,0 @@ -package no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.serdes - -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinFeature -import com.fasterxml.jackson.module.kotlin.KotlinModule -import com.fasterxml.jackson.module.kotlin.readValue -import no.nav.paw.arbeidssokerregisteret.intern.v1.Avsluttet -import no.nav.paw.arbeidssokerregisteret.intern.v1.Avvist -import no.nav.paw.arbeidssokerregisteret.intern.v1.AvvistStoppAvPeriode -import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse -import no.nav.paw.arbeidssokerregisteret.intern.v1.OpplysningerOmArbeidssoekerMottatt -import no.nav.paw.arbeidssokerregisteret.intern.v1.Startet -import no.nav.paw.arbeidssokerregisteret.intern.v1.avsluttetHendelseType -import no.nav.paw.arbeidssokerregisteret.intern.v1.avvistHendelseType -import no.nav.paw.arbeidssokerregisteret.intern.v1.avvistStoppAvPeriodeHendelseType -import no.nav.paw.arbeidssokerregisteret.intern.v1.opplysningerOmArbeidssoekerHendelseType -import no.nav.paw.arbeidssokerregisteret.intern.v1.startetHendelseType -import org.apache.kafka.common.serialization.Deserializer -import org.apache.kafka.common.serialization.Serde -import org.apache.kafka.common.serialization.Serializer - -class HendelseSerde : Serde { - private val objectMapper = hendelseObjectMapper() - override fun serializer() = HendelseSerializer(objectMapper) - override fun deserializer() = HendelseDeserializer(objectMapper) -} - -class HendelseSerializer(private val objectMapper: ObjectMapper): Serializer { - override fun serialize(topic: String?, data: Hendelse?): ByteArray { - return data?.let { - objectMapper.writeValueAsBytes(it) - } ?: ByteArray(0) - } -} - -class HendelseDeserializer(private val objectMapper: ObjectMapper): Deserializer { - override fun deserialize(topic: String?, data: ByteArray?): Hendelse? { - if (data == null) return null - return deserialize(objectMapper, data) - } -} - -private fun hendelseObjectMapper(): ObjectMapper = ObjectMapper() - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .registerModules( - KotlinModule.Builder() - .withReflectionCacheSize(512) - .configure(KotlinFeature.NullToEmptyCollection, true) - .configure(KotlinFeature.NullToEmptyMap, true) - .configure(KotlinFeature.NullIsSameAsDefault, false) - .configure(KotlinFeature.SingletonSupport, false) - .configure(KotlinFeature.StrictNullChecks, false) - .build(), - JavaTimeModule() - ) - -fun deserialize(objectMapper: ObjectMapper, json: ByteArray): Hendelse { - val node = objectMapper.readTree(json) - return when (val hendelseType = node.get("hendelseType")?.asText()) { - startetHendelseType -> objectMapper.readValue(node.traverse()) - avsluttetHendelseType -> objectMapper.readValue(node.traverse()) - avvistHendelseType -> objectMapper.readValue(node.traverse()) - avvistStoppAvPeriodeHendelseType -> objectMapper.readValue(node.traverse()) - opplysningerOmArbeidssoekerHendelseType -> objectMapper.readValue(node.traverse()) - else -> throw IllegalArgumentException("Ukjent hendelse type: '$hendelseType'") - } -} \ No newline at end of file diff --git a/apps/utgang-pdl/src/test/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/TestScope.kt b/apps/utgang-pdl/src/test/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/TestScope.kt index 4dd9d08a..a56519ac 100644 --- a/apps/utgang-pdl/src/test/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/TestScope.kt +++ b/apps/utgang-pdl/src/test/kotlin/no/nav/paw/arbeidssoekerregisteret/utgang/pdl/TestScope.kt @@ -6,11 +6,11 @@ import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde import io.micrometer.prometheusmetrics.PrometheusConfig import io.micrometer.prometheusmetrics.PrometheusMeterRegistry import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.appTopology -import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.serdes.HendelseSerde import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.serdes.HendelseState import no.nav.paw.arbeidssoekerregisteret.utgang.pdl.kafka.serdes.HendelseStateSerde import no.nav.paw.arbeidssokerregisteret.api.v1.Periode import no.nav.paw.arbeidssokerregisteret.intern.v1.Hendelse +import no.nav.paw.arbeidssokerregisteret.intern.v1.HendelseSerde import no.nav.paw.config.hoplite.loadNaisOrLocalConfiguration import no.nav.paw.pdl.graphql.generated.hentforenkletstatusbolk.HentPersonBolkResult import org.apache.avro.specific.SpecificRecord diff --git a/domain/arbeidssoeker-regler/build.gradle.kts b/domain/arbeidssoeker-regler/build.gradle.kts new file mode 100644 index 00000000..78300660 --- /dev/null +++ b/domain/arbeidssoeker-regler/build.gradle.kts @@ -0,0 +1,43 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + kotlin("jvm") + id("org.openapi.generator") + application + id("com.google.cloud.tools.jib") +} + +val baseImage: String by project +val jvmMajorVersion: String by project + +dependencies { + implementation(pawClients.pawPdlClient) + implementation(project(":domain:interne-hendelser")) + api(arrow.core) + testImplementation(ktorServer.testJvm) + testImplementation(testLibs.runnerJunit5) + testImplementation(testLibs.assertionsCore) + testImplementation(testLibs.testContainers) + testImplementation(testLibs.mockOauth2Server) + testImplementation(testLibs.mockk) +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(jvmMajorVersion)) + } +} + +application { + mainClass.set("no.nav.paw.arbeidssokerregisteret.ApplicationKt") +} + +tasks.withType().configureEach { + compilerOptions { + freeCompilerArgs.add("-Xcontext-receivers") + } +} + +tasks.named("test") { + useJUnitPlatform() +} diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/InngangsRegler.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/InngangsRegler.kt new file mode 100644 index 00000000..0afdd1c1 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/InngangsRegler.kt @@ -0,0 +1,48 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* + +val reglerForInngangIPrioritertRekkefolge: List = listOf( + "Person ikke funnet"( + PersonIkkeFunnet, + id = IkkeFunnet, + vedTreff = ::problem + ), + "Er registrert som død"( + ErDoed, + id = Doed, + vedTreff = ::problem + ), + "Er forhåndsgodkjent av ansatt"( + ErForhaandsgodkjent, + id = ForhaandsgodkjentAvAnsatt, + vedTreff = ::ok + ), + "Er bosatt i Norge i henhold Folkeregisterloven, men er under 18 år"( + ErUnder18Aar, + BosattEtterFregLoven, + id = Under18Aar, + vedTreff = ::problem + ), + "Kunne ikke fastslå alder"( + UkjentFoedselsaar, + UkjentFoedselsdato, + id = UkjentAlder, + vedTreff = ::problem + ), + "Er registrert som savnet"( + ErSavnet, + id = Savnet, + vedTreff = ::problem + ), + "Er over 18 år, er bosatt i Norge i henhold Folkeregisterloven"( + ErOver18Aar, + BosattEtterFregLoven, + id = Over18AarOgBosattEtterFregLoven, + vedTreff = ::ok + ), + "Avvist fordi personen ikke er bosatt i Norge i henhold til folkeregisterloven"( + id = IkkeBosattINorgeIHenholdTilFolkeregisterloven, + vedTreff = ::problem + ) +) diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt new file mode 100644 index 00000000..7714c778 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Regel.kt @@ -0,0 +1,20 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import arrow.core.Either +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning + +data class Regel( + val id: RegelId, + /** + * Beskrivelse av regelen + */ + val beskrivelse: String, + /** + * Opplysninger som må være tilstede for at regelen skal være sann + */ + val opplysninger: List, + + private val vedTreff: (Regel, Iterable) -> Either +) { + fun vedTreff(opplysning: Iterable): Either = vedTreff(this, opplysning) +} \ No newline at end of file diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensions.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensions.kt new file mode 100644 index 00000000..01f46c66 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelExtensions.kt @@ -0,0 +1,57 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import arrow.core.Either +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning as HendelseOpplysning + + +operator fun String.invoke( + vararg opplysninger: Opplysning, + id: RegelId, + vedTreff: (Regel, Iterable) -> Either +) = Regel( + id = id, + beskrivelse = this, + vedTreff = vedTreff, + opplysninger = opplysninger.toList() +) + +fun Regel.evaluer(samletOpplysning: Iterable): Boolean = opplysninger.all { samletOpplysning.contains(it) } + +fun List.evaluer(opplysninger: Iterable): Either = + filter { regel -> regel.evaluer(opplysninger) } + .map { regel -> regel.vedTreff(opplysninger) } + .first() + +fun domeneOpplysningTilHendelseOpplysning(opplysning: DomeneOpplysning): HendelseOpplysning = + when (opplysning) { + DomeneOpplysning.BarnFoedtINorgeUtenOppholdstillatelse -> HendelseOpplysning.BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE + DomeneOpplysning.BosattEtterFregLoven -> HendelseOpplysning.BOSATT_ETTER_FREG_LOVEN + DomeneOpplysning.Dnummer -> HendelseOpplysning.DNUMMER + DomeneOpplysning.ErDoed -> HendelseOpplysning.DOED + DomeneOpplysning.ErEuEoesStatsborger -> HendelseOpplysning.ER_EU_EOES_STATSBORGER + DomeneOpplysning.ErForhaandsgodkjent -> HendelseOpplysning.FORHAANDSGODKJENT_AV_ANSATT + DomeneOpplysning.ErGbrStatsborger -> HendelseOpplysning.ER_GBR_STATSBORGER + DomeneOpplysning.ErOver18Aar -> HendelseOpplysning.ER_OVER_18_AAR + DomeneOpplysning.ErSavnet -> HendelseOpplysning.SAVNET + DomeneOpplysning.ErUnder18Aar -> HendelseOpplysning.ER_UNDER_18_AAR + DomeneOpplysning.HarGyldigOppholdstillatelse -> HendelseOpplysning.HAR_GYLDIG_OPPHOLDSTILLATELSE + DomeneOpplysning.HarNorskAdresse -> HendelseOpplysning.HAR_NORSK_ADRESSE + DomeneOpplysning.HarUtenlandskAdresse -> HendelseOpplysning.HAR_UTENLANDSK_ADRESSE + DomeneOpplysning.IkkeBosatt -> HendelseOpplysning.IKKE_BOSATT + DomeneOpplysning.IkkeMuligAAIdentifisereSisteFlytting -> HendelseOpplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING + DomeneOpplysning.IngenAdresseFunnet -> HendelseOpplysning.INGEN_ADRESSE_FUNNET + DomeneOpplysning.IngenFlytteInformasjon -> HendelseOpplysning.INGEN_FLYTTE_INFORMASJON + DomeneOpplysning.IngenInformasjonOmOppholdstillatelse -> HendelseOpplysning.INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE + DomeneOpplysning.OpphoertIdentitet -> HendelseOpplysning.OPPHOERT_IDENTITET + DomeneOpplysning.OppholdstillatelseUtgaaatt -> HendelseOpplysning.OPPHOLDSTILATELSE_UTGAATT + DomeneOpplysning.PersonIkkeFunnet -> HendelseOpplysning.PERSON_IKKE_FUNNET + DomeneOpplysning.SisteFlyttingVarInnTilNorge -> HendelseOpplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE + DomeneOpplysning.SisteFlyttingVarUtAvNorge -> HendelseOpplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE + DomeneOpplysning.TokenxPidIkkeFunnet -> HendelseOpplysning.TOKENX_PID_IKKE_FUNNET + DomeneOpplysning.UkjentFoedselsaar -> HendelseOpplysning.UKJENT_FOEDSELSAAR + DomeneOpplysning.UkjentFoedselsdato -> HendelseOpplysning.UKJENT_FOEDSELSDATO + DomeneOpplysning.UkjentForenkletFregStatus -> HendelseOpplysning.UKJENT_FORENKLET_FREG_STATUS + DomeneOpplysning.UkjentStatusForOppholdstillatelse -> HendelseOpplysning.UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE + } diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt new file mode 100644 index 00000000..0c76a76e --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/RegelId.kt @@ -0,0 +1,39 @@ +package no.nav.paw.arbeidssokerregisteret.application + +interface RegelId { + val id: String +} + +sealed interface DomeneRegelId : RegelId + +data object IkkeFunnet : DomeneRegelId { + override val id: String = "IKKE_FUNNET" +} + +data object Savnet : DomeneRegelId { + override val id: String = "SAVNET" +} + +data object Doed : DomeneRegelId { + override val id: String = "DOED" +} + +data object Under18Aar : DomeneRegelId { + override val id: String = "UNDER_18_AAR" +} + +data object IkkeBosattINorgeIHenholdTilFolkeregisterloven : DomeneRegelId { + override val id: String = "IKKE_BOSATT_I_NORGE_I_HENHOLD_TIL_FOLKEREGISTERLOVEN" +} + +data object ForhaandsgodkjentAvAnsatt : DomeneRegelId { + override val id: String = "FORHAANDSGODKJENT_AV_ANSATT" +} + +data object Over18AarOgBosattEtterFregLoven : DomeneRegelId { + override val id: String = "OVER_18_AAR_OG_BOSATT_ETTER_FREG_LOVEN" +} + +data object UkjentAlder : DomeneRegelId { + override val id: String = "UKJENT_ALDER" +} \ No newline at end of file diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt new file mode 100644 index 00000000..41661fba --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/Resultat.kt @@ -0,0 +1,19 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import arrow.core.Either +import arrow.core.left +import arrow.core.right +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning + +data class Problem( + val opplysning: Iterable, + val regel: Regel +) + +data class OK( + val opplysning: Iterable, + val regel: Regel +) + +fun ok(regel: Regel, opplysning: Iterable): Either = OK(opplysning, regel).right() +fun problem(regel: Regel, opplysning: Iterable): Either = Problem(opplysning, regel).left() \ No newline at end of file diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AddresseOpplysning.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AddresseOpplysning.kt new file mode 100644 index 00000000..7a96e08d --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AddresseOpplysning.kt @@ -0,0 +1,15 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* +import no.nav.paw.pdl.graphql.generated.hentperson.Bostedsadresse + +fun adreseOpplysning(adresse: Bostedsadresse?): Opplysning { + return when { + adresse == null -> IngenAdresseFunnet + adresse.vegadresse?.kommunenummer != null -> HarNorskAdresse + adresse.matrikkeladresse?.kommunenummer != null -> HarNorskAdresse + adresse.ukjentBosted?.bostedskommune != null -> HarNorskAdresse + adresse.utenlandskAdresse != null -> HarUtenlandskAdresse + else -> IngenAdresseFunnet + } +} diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AlderFakta.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AlderOpplysning.kt similarity index 53% rename from apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AlderFakta.kt rename to domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AlderOpplysning.kt index 907823bd..48176a74 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/AlderFakta.kt +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/AlderOpplysning.kt @@ -1,23 +1,24 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta +package no.nav.paw.arbeidssokerregisteret.application.opplysninger -import no.nav.paw.arbeidssokerregisteret.application.Opplysning import no.nav.paw.pdl.graphql.generated.hentperson.Foedsel +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* import java.time.LocalDate import java.time.Month -fun alderFakta(foedsel: Foedsel?): Set { +fun alderOpplysning(foedsel: Foedsel?): Set { val dateOfBirth = foedsel?.foedselsdato?.let(LocalDate::parse) - val lastDayInYearOfBirth = { foedsel?.foedselsaar?.let { foedselsAar -> LocalDate.of(foedselsAar, Month.DECEMBER, 31) } } + val lastDayInYearOfBirth = + { foedsel?.foedselsaar?.let { foedselsAar -> LocalDate.of(foedselsAar, Month.DECEMBER, 31) } } val dob = dateOfBirth ?: lastDayInYearOfBirth() - val preliminaryEvalResult = if (dateOfBirth != null) emptySet() else setOf(Opplysning.UKJENT_FOEDSELSDATO) + val preliminaryEvalResult = if (dateOfBirth != null) emptySet() else setOf(UkjentFoedselsdato) return if (dob != null) { if (isAtLeast18YearsAgo(dob)) { - preliminaryEvalResult + Opplysning.ER_OVER_18_AAR + preliminaryEvalResult + ErOver18Aar } else { - preliminaryEvalResult + Opplysning.ER_UNDER_18_AAR + preliminaryEvalResult + ErUnder18Aar } } else { - preliminaryEvalResult + Opplysning.UKJENT_FOEDSELSAAR + preliminaryEvalResult + UkjentFoedselsaar } } diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/EuEoesStatsborgerOpplysning.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/EuEoesStatsborgerOpplysning.kt new file mode 100644 index 00000000..713c7532 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/EuEoesStatsborgerOpplysning.kt @@ -0,0 +1,43 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +import no.nav.paw.pdl.graphql.generated.hentperson.Statsborgerskap +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* + +fun euEoesStatsborgerOpplysning(statsborgerskap: List): Set = + statsborgerskap.map { it.land.uppercase() } + .any { it in eea } + .let { return if (it) setOf(ErEuEoesStatsborger) else emptySet() } + +val eea = setOf( + "BEL", + "BGR", + "DNK", + "EST", + "FIN", + "FRA", + "GRC", + "IRL", + "ISL", + "ITA", + "HRV", + "CYP", + "LVA", + "LIE", + "LTU", + "LUX", + "MLT", + "NLD", + "NOR", + "POL", + "PRT", + "ROU", + "SVK", + "SVN", + "ESP", + "SWE", + "CZE", + "DEU", + "HUN", + "AUT", + "CHE" +).map { it.uppercase() } \ No newline at end of file diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/ForenkletFRegOpplysning.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/ForenkletFRegOpplysning.kt new file mode 100644 index 00000000..b0f502b6 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/ForenkletFRegOpplysning.kt @@ -0,0 +1,19 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +import no.nav.paw.pdl.graphql.generated.hentperson.Folkeregisterpersonstatus +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* + +fun forenkletFregOpplysning(status: List): Set = + status.map { it.forenkletStatus } + .map { it.uppercase() } + .map { enkelFolkeRegStatusTilOpplysning[it] ?: UkjentForenkletFregStatus } + .toSet() + +private val enkelFolkeRegStatusTilOpplysning: Map = mapOf( + "bosattEtterFolkeregisterloven".uppercase() to BosattEtterFregLoven, + "ikkeBosatt".uppercase() to IkkeBosatt, + "doedIFolkeregisteret".uppercase() to ErDoed, + "forsvunnet".uppercase() to ErSavnet, + "opphoert".uppercase() to OpphoertIdentitet, + "dNummer".uppercase() to Dnummer +) diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/GbrStatsborgerOpplysning.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/GbrStatsborgerOpplysning.kt new file mode 100644 index 00000000..fdc6a7f3 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/GbrStatsborgerOpplysning.kt @@ -0,0 +1,10 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +import no.nav.paw.pdl.graphql.generated.hentperson.Statsborgerskap +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* + +fun gbrStatsborgerOpplysning(statsborgerskap: List): Set = + statsborgerskap.map { it.land.uppercase() } + .any { it == "GBR" } + .let { return if (it) setOf(ErGbrStatsborger) else emptySet() } + diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/OppholdtillatelseOpplysning.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/OppholdtillatelseOpplysning.kt new file mode 100644 index 00000000..2b005fab --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/OppholdtillatelseOpplysning.kt @@ -0,0 +1,22 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +import no.nav.paw.pdl.graphql.generated.enums.Oppholdstillatelse +import no.nav.paw.pdl.graphql.generated.hentperson.Opphold +import java.time.LocalDate +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* + + +fun oppholdstillatelseOpplysning(oppholdtillatelse: Opphold?): Opplysning { + val tilDato = oppholdtillatelse?.oppholdTil?.let(LocalDate::parse) + val utloept = tilDato?.isBefore(LocalDate.now()) ?: false + return if (utloept) { + OppholdstillatelseUtgaaatt + } else + when (oppholdtillatelse?.type) { + Oppholdstillatelse.MIDLERTIDIG -> HarGyldigOppholdstillatelse + Oppholdstillatelse.PERMANENT -> HarGyldigOppholdstillatelse + Oppholdstillatelse.OPPLYSNING_MANGLER -> BarnFoedtINorgeUtenOppholdstillatelse + Oppholdstillatelse.__UNKNOWN_VALUE -> UkjentStatusForOppholdstillatelse + null -> IngenInformasjonOmOppholdstillatelse + } +} diff --git a/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/Opplysninger.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/Opplysninger.kt new file mode 100644 index 00000000..7cd7a808 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/Opplysninger.kt @@ -0,0 +1,159 @@ +package no.nav.paw.arbeidssokerregisteret.application.opplysninger + +interface Opplysning { + val id: String + val beskrivelse: String +} + + +infix operator fun Opplysning.plus(opplysning: Opplysning): Set = setOf(this, opplysning) +sealed interface DomeneOpplysning: Opplysning { + + data object ErForhaandsgodkjent : DomeneOpplysning { + override val id = "FORHAANDSGODKJENT_AV_ANSATT" + override val beskrivelse = "Registrering er forhåndsgodkjent av NAV-ansatt" + } + + data object ErOver18Aar : DomeneOpplysning { + override val id = "ER_OVER_18_AAR" + override val beskrivelse = "Personen start/stopp av periode utføres på er over 18 år" + } + + data object ErUnder18Aar : DomeneOpplysning { + override val id = "ER_UNDER_18_AAR" + override val beskrivelse = "Personen start/stopp av periode utføres på er under 18 år" + } + + data object ErEuEoesStatsborger : DomeneOpplysning { + override val id = "ER_EU_EOES_STATSBORGER" + override val beskrivelse = "Personen start/stopp av periode utføres på er EØS/EU statsborger" + } + + data object ErGbrStatsborger : DomeneOpplysning { + override val id = "ER_GBR_STATSBORGER" + override val beskrivelse = "Personen start/stopp av periode utføres på er britisk statsborger" + } + + data object UkjentFoedselsdato : DomeneOpplysning { + override val id = "UKJENT_FOEDSELSDATO" + override val beskrivelse = "Personen start/stopp av periode utføres på har ukjent fødselsdato" + } + + data object UkjentFoedselsaar : DomeneOpplysning { + override val id = "UKJENT_FOEDSELSAAR" + override val beskrivelse = "Personen start/stopp av periode utføres på har ukjent fødselsår" + } + + data object TokenxPidIkkeFunnet : DomeneOpplysning { + override val id = "TOKENX_PID_IKKE_FUNNET" + override val beskrivelse = + "Innlogget bruker er ikke en logget inn via TOKENX med PID(dvs ikke sluttbruker via ID-Porten)" + } + + data object OpphoertIdentitet : DomeneOpplysning { + override val id = "OPPHOERT_IDENTITET" + override val beskrivelse = + "Personen start/stopp av periode utføres på har opphørt identitet(annulert i Folkeregisteret)" + } + + data object IkkeBosatt : DomeneOpplysning { + override val id = "IKKE_BOSATT" + override val beskrivelse = + "Personen start/stopp av periode utføres på er ikke bosatt i Norge(eventuelt er innlytting anullert)" + } + + data object ErDoed : DomeneOpplysning { + override val id = "DOED" + override val beskrivelse = "Personen start/stopp av periode utføres på er død" + } + + data object ErSavnet : DomeneOpplysning { + override val id = "SAVNET" + override val beskrivelse = "Personen start/stopp av periode utføres på er savnet" + } + + data object HarNorskAdresse : DomeneOpplysning { + override val id = "HAR_NORSK_ADRESSE" + override val beskrivelse = "Personen start/stopp av periode utføres på har norsk adresse" + } + + data object HarUtenlandskAdresse : DomeneOpplysning { + override val id = "HAR_UTENLANDSK_ADRESSE" + override val beskrivelse = "Personen start/stopp av periode utføres på har utenlandsk adresse" + } + + data object IngenAdresseFunnet : DomeneOpplysning { + override val id = "INGEN_ADRESSE_FUNNET" + override val beskrivelse = "Personen start/stopp av periode utføres på har ingen adresse i våre systemer" + } + + data object BosattEtterFregLoven : DomeneOpplysning { + override val id = "BOSATT_ETTER_FREG_LOVEN" + override val beskrivelse = + "Personen start/stopp av periode utføres på er bosatt i Norge i henhold til Folkeregisterloven" + } + + data object Dnummer : DomeneOpplysning { + override val id = "DNUMMER" + override val beskrivelse = "Personen start/stopp av periode utføres på har D-nummer" + } + + data object UkjentForenkletFregStatus : DomeneOpplysning { + override val id = "UKJENT_FORENKLET_FREG_STATUS" + override val beskrivelse = "Personen start/stopp av periode utføres på har ukjent forenklet folkeregisterstatus" + } + + data object HarGyldigOppholdstillatelse : DomeneOpplysning { + override val id = "HAR_GYLDIG_OPPHOLDSTILLATELSE" + override val beskrivelse = "Personen start/stopp av periode utføres på har gyldig oppholdstillatelse" + } + + data object OppholdstillatelseUtgaaatt : DomeneOpplysning { + override val id = "OPPHOLDSTILATELSE_UTGAATT" + override val beskrivelse = "Personen start/stopp av periode utføres på har oppholdstillatelse som er utgått" + } + + data object BarnFoedtINorgeUtenOppholdstillatelse : DomeneOpplysning { + override val id = "BARN_FOEDT_I_NORGE_UTEN_OPPHOLDSTILLATELSE" + override val beskrivelse = "Personen start/stopp av periode utføres på er født i Norge uten oppholdstillatelse" + } + + data object IngenInformasjonOmOppholdstillatelse : DomeneOpplysning { + override val id = "INGEN_INFORMASJON_OM_OPPHOLDSTILLATELSE" + override val beskrivelse = + "Personen start/stopp av periode utføres på har ingen informasjon om oppholdstillatelse" + } + + data object UkjentStatusForOppholdstillatelse : DomeneOpplysning { + override val id = "UKJENT_STATUS_FOR_OPPHOLDSTILLATELSE" + override val beskrivelse = "Personen start/stopp av periode utføres på har ukjent status for oppholdstillatelse" + } + + data object PersonIkkeFunnet : DomeneOpplysning { + override val id = "PERSON_IKKE_FUNNET" + override val beskrivelse = "Personen start/stopp av periode utføres på er ikke funnet i våre systemer" + } + + data object SisteFlyttingVarUtAvNorge : DomeneOpplysning { + override val id = "SISTE_FLYTTING_VAR_UT_AV_NORGE" + override val beskrivelse = + "Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste var ut av Norge" + } + + data object SisteFlyttingVarInnTilNorge : DomeneOpplysning { + override val id = "SISTE_FLYTTING_VAR_INN_TIL_NORGE" + override val beskrivelse = + "Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste var inn til Norge" + } + + data object IkkeMuligAAIdentifisereSisteFlytting : DomeneOpplysning { + override val id = "IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING" + override val beskrivelse = + "Personen start/stopp av periode utføres på har en eller flere flyttinger hvorav den siste ikke er mulig å identifisere" + } + + data object IngenFlytteInformasjon : DomeneOpplysning { + override val id = "INGEN_FLYTTE_INFORMASJON" + override val beskrivelse = "Personen start/stopp av periode utføres på har ingen flytte informasjon" + } +} \ No newline at end of file diff --git a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/UtflyttingFakta.kt b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/UtflyttingOpplysning.kt similarity index 56% rename from apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/UtflyttingFakta.kt rename to domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/UtflyttingOpplysning.kt index 835453c5..5682e90d 100644 --- a/apps/api-start-stopp-perioder/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/fakta/UtflyttingFakta.kt +++ b/domain/arbeidssoeker-regler/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/application/opplysninger/UtflyttingOpplysning.kt @@ -1,17 +1,17 @@ -package no.nav.paw.arbeidssokerregisteret.application.fakta +package no.nav.paw.arbeidssokerregisteret.application.opplysninger -import no.nav.paw.arbeidssokerregisteret.application.Opplysning import no.nav.paw.pdl.graphql.generated.hentperson.InnflyttingTilNorge import no.nav.paw.pdl.graphql.generated.hentperson.UtflyttingFraNorge import java.time.LocalDate import java.time.LocalDateTime +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.* -fun utflyttingFakta( +fun utflyttingOpplysning( inn: List, ut: List ): Opplysning = when { - inn.isEmpty() && ut.isEmpty() -> Opplysning.INGEN_FLYTTE_INFORMASJON + inn.isEmpty() && ut.isEmpty() -> IngenFlytteInformasjon inn.isNotEmpty() && ut.isNotEmpty() -> { val flyttinger = inn.map { flyttingInn -> Flytting(inn = true, dato = flyttingInn.folkeregistermetadata?.ajourholdstidspunkt?.let(LocalDateTime::parse)?.toLocalDate()) @@ -19,17 +19,17 @@ fun utflyttingFakta( Flytting(inn = false, dato = utflytting.utflyttingsdato?.let(LocalDate::parse)) } when { - flyttinger.distinctBy { it.dato }.size < 2 -> Opplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING - flyttinger.any { it.dato == null } -> Opplysning.IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING + flyttinger.distinctBy { it.dato }.size < 2 -> IkkeMuligAAIdentifisereSisteFlytting + flyttinger.any { it.dato == null } -> IkkeMuligAAIdentifisereSisteFlytting else -> { val sisteFlytting = flyttinger.maxByOrNull { it.dato!! } - if (sisteFlytting?.inn == true) Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE - else Opplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE + if (sisteFlytting?.inn == true) SisteFlyttingVarInnTilNorge + else SisteFlyttingVarUtAvNorge } } } - inn.isNotEmpty() -> Opplysning.SISTE_FLYTTING_VAR_INN_TIL_NORGE - else -> Opplysning.SISTE_FLYTTING_VAR_UT_AV_NORGE + inn.isNotEmpty() -> SisteFlyttingVarInnTilNorge + else -> SisteFlyttingVarUtAvNorge } private data class Flytting( diff --git a/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EuEoesStatsborgerTest.kt b/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EuEoesStatsborgerTest.kt new file mode 100644 index 00000000..aba19d69 --- /dev/null +++ b/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/EuEoesStatsborgerTest.kt @@ -0,0 +1,44 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.collections.shouldContain +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.ErEuEoesStatsborger +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.Opplysning +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.euEoesStatsborgerOpplysning +import no.nav.paw.pdl.graphql.generated.hentperson.Metadata +import no.nav.paw.pdl.graphql.generated.hentperson.Statsborgerskap + +class EuEoesStatsborgerTest : FreeSpec({ + "Test for EU/EØS statsborgere" - { + alpha3EuEeaCountries + .map { cuntry -> Statsborgerskap(cuntry, Metadata(emptyList())) } + .forEach { statsborgerskap -> + "Statsborgerskap: ${statsborgerskap.land} er medlem av EU/EØS" { + euEoesStatsborgerOpplysning(listOf(statsborgerskap)) shouldContain ErEuEoesStatsborger + } + } + "flere statsborgerskap" { + val statsborgerskap0 = Statsborgerskap("NOR", Metadata(emptyList())) + val statsborgerskap1 = Statsborgerskap("GBR", Metadata(emptyList())) + val statsborgerskap2 = Statsborgerskap("USA", Metadata(emptyList())) + euEoesStatsborgerOpplysning(listOf( + statsborgerskap0, + statsborgerskap1, + statsborgerskap2 + )) shouldContain ErEuEoesStatsborger + } + } + "Test for ikke EU/EØS statsborgere" - { + val statsborgerskap = Statsborgerskap("USA", Metadata(emptyList())) + "Statsborgerskap: ${statsborgerskap.land} er ikke medlem av EU/EØS" { + euEoesStatsborgerOpplysning(listOf(statsborgerskap)).isEmpty() + } + } +}) + +val alpha3EuEeaCountries = setOf( + "AUT", "BEL", "BGR", "HRV", "CZE", "DNK", "EST", "FIN", "FRA", + "DEU", "GRC", "HUN", "IRL", "ITA", "LVA", "LTU", "LUX", "MLT", + "NLD", "POL", "PRT", "ROU", "SVK", "SVN", "ESP", "SWE" +) + diff --git a/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/GbrStatsborgerTest.kt b/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/GbrStatsborgerTest.kt new file mode 100644 index 00000000..05c63e6f --- /dev/null +++ b/domain/arbeidssoeker-regler/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/application/GbrStatsborgerTest.kt @@ -0,0 +1,35 @@ +package no.nav.paw.arbeidssokerregisteret.application + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.collections.shouldContain +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.DomeneOpplysning.ErGbrStatsborger +import no.nav.paw.arbeidssokerregisteret.application.opplysninger.gbrStatsborgerOpplysning +import no.nav.paw.pdl.graphql.generated.hentperson.Metadata +import no.nav.paw.pdl.graphql.generated.hentperson.Statsborgerskap + +class GbrStatsborgerTest : FreeSpec({ + "Test for GBR statsborgere" - { + "bare et statsborgerskap" { + val statsborgerskap = Statsborgerskap("GBR", Metadata(emptyList())) + gbrStatsborgerOpplysning(listOf(statsborgerskap)) shouldContain ErGbrStatsborger + } + "flere statsborgerskap" { + val statsborgerskap0 = Statsborgerskap("NOR", Metadata(emptyList())) + val statsborgerskap1 = Statsborgerskap("GBR", Metadata(emptyList())) + val statsborgerskap2 = Statsborgerskap("USA", Metadata(emptyList())) + gbrStatsborgerOpplysning( + listOf( + statsborgerskap0, + statsborgerskap1, + statsborgerskap2 + ) + ) shouldContain ErGbrStatsborger + } + } + "Test for ikke GBR statsborgere" - { + val statsborgerskap = Statsborgerskap("NOR", Metadata(emptyList())) + "Statsborgerskap: ${statsborgerskap.land} er ikke GBR" { + gbrStatsborgerOpplysning(listOf(statsborgerskap)).isEmpty() + } + } +}) diff --git a/domain/interne-hendelser/build.gradle.kts b/domain/interne-hendelser/build.gradle.kts index 57e99fe9..50f5d905 100644 --- a/domain/interne-hendelser/build.gradle.kts +++ b/domain/interne-hendelser/build.gradle.kts @@ -8,6 +8,13 @@ dependencies { compileOnly(jackson.kotlin) compileOnly(jackson.core) compileOnly(orgApacheKafka.kafkaClients) + + testImplementation(testLibs.runnerJunit5) + testImplementation(testLibs.assertionsCore) + testImplementation(orgApacheKafka.kafkaClients) + testImplementation(jackson.datatypeJsr310) + testImplementation(jackson.kotlin) + testImplementation(jackson.core) } val jvmMajorVersion: String by project @@ -38,3 +45,8 @@ java { languageVersion = JavaLanguageVersion.of(jvmMajorVersion) } } + +tasks.named("test") { + useJUnitPlatform() +} + diff --git a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/Avsluttet.kt b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/Avsluttet.kt index 54cadd7c..83d530ba 100644 --- a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/Avsluttet.kt +++ b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/Avsluttet.kt @@ -1,6 +1,7 @@ package no.nav.paw.arbeidssokerregisteret.intern.v1 import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning import java.util.* data class Avsluttet( @@ -8,7 +9,8 @@ data class Avsluttet( override val id: Long, override val identitetsnummer: String, override val metadata: Metadata, + override val opplysninger: Set = emptySet(), val periodeId: UUID? = null -): Hendelse { +): Hendelse, HarOpplysninger { override val hendelseType: String = avsluttetHendelseType } \ No newline at end of file diff --git a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/AvvistStoppAvPeriode.kt b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/AvvistStoppAvPeriode.kt index 319bd190..bbc376da 100644 --- a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/AvvistStoppAvPeriode.kt +++ b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/AvvistStoppAvPeriode.kt @@ -1,13 +1,15 @@ package no.nav.paw.arbeidssokerregisteret.intern.v1 import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Metadata +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning import java.util.* data class AvvistStoppAvPeriode( override val hendelseId: UUID, override val id: Long, override val identitetsnummer: String, - override val metadata: Metadata -) : Hendelse { + override val metadata: Metadata, + override val opplysninger: Set = emptySet() +) : Hendelse, HarOpplysninger { override val hendelseType: String = avvistStoppAvPeriodeHendelseType } \ No newline at end of file diff --git a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerde.kt b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerde.kt index 7500091d..3bb36813 100644 --- a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerde.kt +++ b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerde.kt @@ -48,6 +48,7 @@ class HendelseDeserializer(private val objectMapper: ObjectMapper) : Deserialize private fun hendelseObjectMapper(): ObjectMapper = ObjectMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) .registerModules( KotlinModule.Builder() .withReflectionCacheSize(512) diff --git a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/vo/Opplysning.kt b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/vo/Opplysning.kt index 3ee0277e..98fe8d39 100644 --- a/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/vo/Opplysning.kt +++ b/domain/interne-hendelser/src/main/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/vo/Opplysning.kt @@ -1,5 +1,7 @@ package no.nav.paw.arbeidssokerregisteret.intern.v1.vo +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue + enum class Opplysning { FORHAANDSGODKJENT_AV_ANSATT, SAMME_SOM_INNLOGGET_BRUKER, @@ -31,5 +33,9 @@ enum class Opplysning { SISTE_FLYTTING_VAR_UT_AV_NORGE, SISTE_FLYTTING_VAR_INN_TIL_NORGE, IKKE_MULIG_AA_IDENTIFISERE_SISTE_FLYTTING, - INGEN_FLYTTE_INFORMASJON + INGEN_FLYTTE_INFORMASJON, + ER_EU_EOES_STATSBORGER, + ER_GBR_STATSBORGER, + @JsonEnumDefaultValue + UKJENT_OPPLYSNING } \ No newline at end of file diff --git a/domain/interne-hendelser/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerdeTest.kt b/domain/interne-hendelser/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerdeTest.kt new file mode 100644 index 00000000..f4f7af48 --- /dev/null +++ b/domain/interne-hendelser/src/test/kotlin/no/nav/paw/arbeidssokerregisteret/intern/v1/HendelseSerdeTest.kt @@ -0,0 +1,61 @@ +package no.nav.paw.arbeidssokerregisteret.intern.v1 + +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeInstanceOf +import no.nav.paw.arbeidssokerregisteret.intern.v1.vo.Opplysning + +class HendelseSerdeTest: FreeSpec({ + val serde = HendelseSerde() + "Test default verdier" - { + "Verifiser at vi kan deserialisere hendelse uten opplysninger" { + serde.deserializer().deserializeFromString(avvistUtenOpplysninger) + } + "Verifisert at vi kan deserialisere hendelse med ukjent opplysning" { + val resultat = serde.deserializer().deserializeFromString(avvistMedUkjentOpplysning) + resultat.shouldBeInstanceOf() + resultat.opplysninger shouldContain Opplysning.IKKE_ANSATT + resultat.opplysninger shouldContain Opplysning.UKJENT_OPPLYSNING + resultat.opplysninger.size shouldBe 2 + } + } +}) + + +val avvistUtenOpplysninger: String = """ +{ + "hendelseId":"723d5d09-83c7-4f83-97fd-35f7c9c5c798", + "id":1, + "identitetsnummer":"12345678901", + "metadata":{ + "tidspunkt":1630404930.000000000, + "utfoertAv":{ + "type":"SYSTEM", + "id":"Testsystem" + }, + "kilde":"Testkilde", + "aarsak":"Testaarsak" + }, + "hendelseType":"intern.v1.avvist" +} +""".trimIndent() + +val avvistMedUkjentOpplysning: String = """ +{ + "hendelseId":"723d5d09-83c7-4f83-97fd-35f7c9c5c798", + "id":1, + "identitetsnummer":"12345678901", + "metadata":{ + "tidspunkt":1630404930.000000000, + "utfoertAv":{ + "type":"SYSTEM", + "id":"Testsystem" + }, + "kilde":"Testkilde", + "aarsak":"Testaarsak" + }, + "hendelseType":"intern.v1.avvist", + "opplysninger":["${Opplysning.IKKE_ANSATT}", "udefinert opplysning"] +} +""".trimIndent() \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index c9697cdf..c32597a8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,6 +24,7 @@ include( "domain:main-avro-schema", "domain:interne-hendelser", "domain:arbeidssoekerregisteret-kotlin", + "domain:arbeidssoeker-regler" ) dependencyResolutionManagement { @@ -51,13 +52,16 @@ dependencyResolutionManagement { } versionCatalogs { // PAW greier - val pawPdlClientVersion = "24.06.10.36-1" + val pawPdlClientVersion = "24.06.24.38-1" val pawAaregClientVersion = "24.01.12.16-1" val arbeidssokerregisteretVersion = "1.9348086045.48-1" + //Arrow + val arrowVersion = "1.2.4" + // NAV - val noNavCommonVersion = "3.2024.05.23_05.46-2b29fa343e8e" - val noNavSecurityVersion = "4.1.7" + val noNavCommonVersion = "3.2024.05.23_05.46-2b29fa343e8e" //https://github.com/navikt/common-java-modules + val noNavSecurityVersion = "5.0.1" //https://github.com/navikt/token-support // Konfigurasjon val comSksamuelHopliteVersion = "2.8.0.RC3" @@ -71,23 +75,23 @@ dependencyResolutionManagement { val comFasterxmlJacksonVersion = "2.17.1" // ---- // - val kotlinExposedVersion = "0.50.0" + val kotlinExposedVersion = "0.51.1" val logstashVersion = "7.4" val logbackVersion = "1.5.6" - val kotestVersion = "5.9.0" + val kotestVersion = "5.9.1" val mockkVersion = "1.13.11" val testContainersVersion = "1.19.8" val mockOauth2ServerVersion = "2.1.5" - val micrometerVersion = "1.13.0" - val otelTargetSdkVersion = "1.36.0" - val otelInstrumentationVersion = "2.1.0" + val micrometerVersion = "1.13.1" + val otelTargetSdkVersion = "1.39.0" + val otelInstrumentationVersion = "2.4.0" val coroutinesVersion = "1.8.1" val rapporteringsSchemaVersion = "24.05.15.2-1" val postgresDriverVersion = "42.7.3" - val flywayVersion = "10.14.0" + val flywayVersion = "10.15.0" fun VersionCatalogBuilder.ktorLib(alias: String, artifactId: String) = - library(alias, "io.ktor", artifactId).version("2.3.11") + library(alias, "io.ktor", artifactId).version("2.3.12") fun VersionCatalogBuilder.ktorLibs(vararg aliases: Pair) = aliases.forEach { (artifactId, alias) -> ktorLib(alias, artifactId) } @@ -96,6 +100,9 @@ dependencyResolutionManagement { create("kotlinx") { library("coroutinesCore", "org.jetbrains.kotlinx", "kotlinx-coroutines-core").version(coroutinesVersion) } + create("arrow") { + library("core", "io.arrow-kt", "arrow-core").version(arrowVersion) + } create("loggingLibs") { library("logbackClassic", "ch.qos.logback", "logback-classic").version(logbackVersion) library("logstashLogbackEncoder", "net.logstash.logback", "logstash-logback-encoder").version(