From c2adfbac38e4152a80cb2ef6f99e6eb748486982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20B=C3=BClow=20Skovborg?= Date: Thu, 31 Oct 2024 13:53:41 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Hindre=20tilgang=20til=20p?= =?UTF-8?q?ersoner=20som=20skal=20holdes=20igjen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Øydis Kind Refsum --- .../api/graphql/query/PersonQuery.kt | 12 ++++++ .../spesialist/api/person/PersonApiDao.kt | 13 +++++++ .../spesialist/api/person/PersonService.kt | 10 +++++ .../spesialist/api/person/PersonApiDaoTest.kt | 38 +++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/graphql/query/PersonQuery.kt b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/graphql/query/PersonQuery.kt index 0b15c52a2..343dfaf30 100644 --- a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/graphql/query/PersonQuery.kt +++ b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/graphql/query/PersonQuery.kt @@ -18,6 +18,7 @@ import no.nav.helse.spesialist.api.graphql.schema.Person import no.nav.helse.spesialist.api.saksbehandler.SaksbehandlerFraApi import org.slf4j.Logger import org.slf4j.LoggerFactory +import java.util.UUID private sealed interface Inputvalidering { class Ok(val fødselsnummer: String) : Inputvalidering @@ -41,6 +42,11 @@ interface PersonoppslagService { tilganger: SaksbehandlerTilganger, ): FetchPersonResult + fun personSkalHoldesIgjen( + fødselsnummer: String, + saksbehandlerOid: UUID, + ): Boolean + fun finnesPersonMedFødselsnummer(fødselsnummer: String): Boolean fun fødselsnumreKnyttetTil(aktørId: String): Set @@ -85,6 +91,12 @@ class PersonQuery( } sikkerLogg.info("Personoppslag på fnr=$fødselsnummer") + // Skal ikke kunne slå opp personer som holdes igjen på grunn av replikeringsfeil + val saksbehandler = env.graphQlContext.get(SAKSBEHANDLER) + if (personoppslagService.personSkalHoldesIgjen(fødselsnummer, saksbehandler.oid)) { + return forbiddenError(fødselsnummer).tilGraphqlResult() + } + val tilganger = env.graphQlContext.get(TILGANGER) return when (val result = personoppslagService.hentPerson(fødselsnummer, tilganger)) { diff --git a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonApiDao.kt b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonApiDao.kt index 6b1aaeb4f..120341e6e 100644 --- a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonApiDao.kt +++ b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonApiDao.kt @@ -5,9 +5,22 @@ import no.nav.helse.db.MedDataSource import no.nav.helse.db.QueryRunner import no.nav.helse.spesialist.api.vedtaksperiode.EnhetDto import java.time.LocalDateTime +import java.util.UUID import javax.sql.DataSource class PersonApiDao(dataSource: DataSource) : QueryRunner by MedDataSource(dataSource) { + fun skalHoldesIgjen( + fødselsnummer: String, + saksbehandlerOid: UUID, + ): Boolean { + return asSQL( + """SELECT true FROM person_som_skal_holdes_igjen WHERE fodselsnummer = :fodselsnummer AND NOT (:oid = ANY(oider_som_kan_sla_opp))""", + "fodselsnummer" to fødselsnummer, "oid" to saksbehandlerOid, + ).singleOrNull { + it.boolean(1) + } ?: false + } + fun personKlargjøres(fødselsnummer: String) { asSQL( "INSERT INTO person_klargjores(fødselsnummer, opprettet) VALUES(:fodselsnummer, :opprettet) ON CONFLICT DO NOTHING", diff --git a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonService.kt b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonService.kt index 4371fea69..f097330ae 100644 --- a/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonService.kt +++ b/spesialist-api/src/main/kotlin/no/nav/helse/spesialist/api/person/PersonService.kt @@ -34,6 +34,7 @@ import no.nav.helse.spesialist.api.varsel.ApiVarselRepository import no.nav.helse.spesialist.api.vergemål.VergemålApiDao import no.nav.helse.spleis.graphql.hentsnapshot.GraphQLPerson import org.slf4j.LoggerFactory +import java.util.UUID private sealed interface HentSnapshotResult { class Ok(val snapshot: Pair) : HentSnapshotResult @@ -108,6 +109,15 @@ class PersonService( return person(fødselsnummer, snapshot, tilganger, reservasjon) } + override fun personSkalHoldesIgjen( + fødselsnummer: String, + saksbehandlerOid: UUID, + ): Boolean = + personApiDao.skalHoldesIgjen( + fødselsnummer, + saksbehandlerOid, + ) + private fun person( fødselsnummer: String, snapshot: Pair, diff --git a/spesialist-api/src/test/kotlin/no/nav/helse/spesialist/api/person/PersonApiDaoTest.kt b/spesialist-api/src/test/kotlin/no/nav/helse/spesialist/api/person/PersonApiDaoTest.kt index e1b62d951..931b87aa5 100644 --- a/spesialist-api/src/test/kotlin/no/nav/helse/spesialist/api/person/PersonApiDaoTest.kt +++ b/spesialist-api/src/test/kotlin/no/nav/helse/spesialist/api/person/PersonApiDaoTest.kt @@ -1,11 +1,17 @@ package no.nav.helse.spesialist.api.person +import kotliquery.queryOf +import kotliquery.sessionOf import no.nav.helse.spesialist.api.DatabaseIntegrationTest import no.nav.helse.spesialist.api.person.Adressebeskyttelse.Ugradert +import no.nav.helse.spesialist.test.lagFødselsnummer +import org.intellij.lang.annotations.Language import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import java.time.LocalDateTime +import java.util.UUID internal class PersonApiDaoTest : DatabaseIntegrationTest() { @@ -15,6 +21,22 @@ internal class PersonApiDaoTest : DatabaseIntegrationTest() { assertTrue(personApiDao.personHarAdressebeskyttelse(FØDSELSNUMMER, Adressebeskyttelse.Fortrolig)) } + @Test + fun `person skal holdes igjen`() { + val fødselsnummer = lagFødselsnummer() + opprettPersonSomSkalHoldesIgjen(fødselsnummer) + assertTrue(personApiDao.skalHoldesIgjen(fødselsnummer, UUID.randomUUID())) + } + + @Test + fun `person skal ikke holdes igjen hvis saksbehandler har fått tilgang eksplisitt`() { + val fødselsnummer = lagFødselsnummer() + opprettPersonSomSkalHoldesIgjen(fødselsnummer) + val saksbehandlerOid = UUID.randomUUID() + giSaksbehandlerTilgangTilPersonSomHoldesIgjen(fødselsnummer, saksbehandlerOid) + assertFalse(personApiDao.skalHoldesIgjen(fødselsnummer, saksbehandlerOid)) + } + @Test fun `person med ugradert adresse er ikke kode 7`() { opprettPerson(adressebeskyttelse = Ugradert) @@ -84,6 +106,22 @@ internal class PersonApiDaoTest : DatabaseIntegrationTest() { assertTrue(personApiDao.klargjøringPågår(FØDSELSNUMMER)) } + private fun opprettPersonSomSkalHoldesIgjen(fødselsnummer: String) { + @Language("PostgreSQL") + val query = """INSERT INTO person_som_skal_holdes_igjen(fodselsnummer, opprettet) VALUES (:fodselsnummer, :opprettet)""" + sessionOf(dataSource).use { session -> + session.run(queryOf(query, mapOf("fodselsnummer" to fødselsnummer, "opprettet" to LocalDateTime.now())).asExecute) + } + } + + private fun giSaksbehandlerTilgangTilPersonSomHoldesIgjen(fødselsnummer: String, saksbehandlerOid: UUID) { + @Language("PostgreSQL") + val query = """UPDATE person_som_skal_holdes_igjen SET oider_som_kan_sla_opp = ARRAY[:oid] WHERE fodselsnummer = :fodselsnummer""" + sessionOf(dataSource).use { session -> + session.run(queryOf(query, mapOf("fodselsnummer" to fødselsnummer, "oid" to saksbehandlerOid)).asExecute) + } + } + private fun harDataNødvendigForVisning() = personApiDao.harDataNødvendigForVisning(FØDSELSNUMMER) private fun assertPersonenErIkkeKlar() = assertFalse(harDataNødvendigForVisning()) private fun assertPersonenErKlar() = assertTrue(harDataNødvendigForVisning())