Skip to content

Commit cc4be4f

Browse files
authored
Samler pip-klienter i egen rest-modul (#1406)
* Samler pip-klienter i egen rest-modul * Finpuss
1 parent f5c58a1 commit cc4be4f

File tree

13 files changed

+633
-1
lines changed

13 files changed

+633
-1
lines changed

integrasjon/arbeidsfordeling-klient/src/main/java/no/nav/vedtak/felles/integrasjon/skjerming/AbstractSkjermetPersonGCPKlient.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import no.nav.vedtak.felles.integrasjon.rest.RestRequest;
1616

1717
// Extend og annoter med endpoint+default og scopes/default + tokenConfig = AzureAD_CC
18-
//@RestClientConfig(tokenConfig = TokenFlow.AZUREAD_CC, endpointProperty = "skjermet.person.rs.url", endpointDefault = "https://skjermede-personer-pip.intern.nav.no/skjermet",
18+
//@RestClientConfig(tokenConfig = TokenFlow.AZUREAD_CC, endpointProperty = "skjermet.person.rs.url", endpointDefault = "https://skjermede-personer-pip.intern.nav.no",
1919
// scopesProperty = "skjermet.person.rs.azure.scope", scopesDefault = "api://prod-gcp.nom.skjermede-personer-pip/.default")
2020
public abstract class AbstractSkjermetPersonGCPKlient implements Skjerming {
2121

integrasjon/pip-klient/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# pip-klient
2+
3+
Samling av pip-klienter som brukes til å henter informasjon for tilgangskontroll og ruting av saker
4+
5+
## Hensikten
6+
7+
Tilby data til applikasjoner som implementerer tilgangskontrollvurderinger
8+
9+
## Integrasjoner
10+
11+
* PDL-PIP-API
12+
* SKJERMET PERSON
13+
* Muligens FP-sak

integrasjon/pip-klient/pom.xml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>no.nav.foreldrepenger.felles.integrasjon</groupId>
6+
<artifactId>felles-integrasjon-pom</artifactId>
7+
<version>0.0.0-SNAPSHOT</version>
8+
</parent>
9+
<artifactId>pip-klient</artifactId>
10+
<packaging>jar</packaging>
11+
<name>Felles :: Integrasjonsendepunkt - pip-klient</name>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>no.nav.foreldrepenger.felles.integrasjon</groupId>
16+
<artifactId>felles-integrasjon-rest-klient</artifactId>
17+
</dependency>
18+
<dependency>
19+
<groupId>jakarta.validation</groupId>
20+
<artifactId>jakarta.validation-api</artifactId>
21+
</dependency>
22+
</dependencies>
23+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package no.nav.vedtak.felles.integrasjon.fpsakpip;
2+
3+
import java.net.URI;
4+
import java.util.List;
5+
import java.util.Objects;
6+
7+
import jakarta.validation.constraints.NotNull;
8+
import jakarta.ws.rs.core.UriBuilder;
9+
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
import no.nav.vedtak.felles.integrasjon.rest.RestClient;
14+
import no.nav.vedtak.felles.integrasjon.rest.RestConfig;
15+
import no.nav.vedtak.felles.integrasjon.rest.RestRequest;
16+
17+
/*
18+
* Informasjon fra skjermingsløsningen til bruk for tilgangskontroll. Registrer klientapps hos nom
19+
*/
20+
21+
// Extend og annoter med @RestClientConfig(tokenConfig = TokenFlow.AZUREAD_CC, application = FpApplication.FPSAK)
22+
public abstract class AbstractForeldrepengerPipKlient implements ForeldrepengerPip {
23+
24+
private static final Logger LOG = LoggerFactory.getLogger(AbstractForeldrepengerPipKlient.class);
25+
26+
private static final String SAK_AKTØR_PATH = "/api/pip/aktoer-for-sak";
27+
28+
private final RestClient restClient;
29+
private final RestConfig restConfig;
30+
31+
private final URI sakAktørerEndpoint;
32+
33+
protected AbstractForeldrepengerPipKlient() {
34+
this(RestClient.client());
35+
}
36+
37+
protected AbstractForeldrepengerPipKlient(RestClient restClient) {
38+
this.restClient = restClient;
39+
this.restConfig = RestConfig.forClient(this.getClass());
40+
this.sakAktørerEndpoint = UriBuilder.fromUri(restConfig.fpContextPath()).path(SAK_AKTØR_PATH).build();
41+
if (!restConfig.tokenConfig().isAzureAD()) {
42+
throw new IllegalArgumentException("Utviklerfeil: klient må annoteres med Azure CC");
43+
}
44+
}
45+
46+
47+
@Override
48+
public List<ForeldrepengerPipAktørId> personerForSak(String saksnummer) {
49+
if (saksnummer == null) {
50+
return List.of();
51+
}
52+
53+
var request = RestRequest.newPOSTJson(new SaksnummerDto(saksnummer), sakAktørerEndpoint, restConfig);
54+
55+
try {
56+
return restClient.sendReturnList(request, ForeldrepengerPipAktørId.class);
57+
} catch (Exception e) {
58+
LOG.info("ForeldrepengerPip fikk feil", e);
59+
}
60+
return restClient.sendReturnList(request, ForeldrepengerPipAktørId.class);
61+
}
62+
63+
public record SaksnummerDto(@NotNull String saksnummer) {
64+
public SaksnummerDto {
65+
Objects.requireNonNull(saksnummer, "saksnummer");
66+
}
67+
}
68+
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package no.nav.vedtak.felles.integrasjon.fpsakpip;
2+
3+
import java.util.List;
4+
5+
public interface ForeldrepengerPip {
6+
7+
List<ForeldrepengerPipAktørId> personerForSak(String fnr);
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package no.nav.vedtak.felles.integrasjon.fpsakpip;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
import java.util.regex.Pattern;
6+
7+
import jakarta.validation.constraints.NotNull;
8+
9+
import com.fasterxml.jackson.annotation.JsonValue;
10+
11+
/**
12+
* Id som genereres fra NAV Aktørregister.
13+
* Denne iden benyttes til interne forhold i Nav og vil ikke endres f.eks. dersom bruker går fra DNR til FNR i Folkeregisteret.
14+
*/
15+
public class ForeldrepengerPipAktørId implements Serializable, Comparable<ForeldrepengerPipAktørId> {
16+
private static final String VALID_REGEXP = "^\\d{13}$";
17+
18+
private static final Pattern VALID = Pattern.compile(VALID_REGEXP, Pattern.CASE_INSENSITIVE);
19+
20+
@JsonValue
21+
@NotNull
22+
@jakarta.validation.constraints.Pattern(regexp = VALID_REGEXP, message = "aktørId ${validatedValue} har ikke gyldig verdi (pattern '{regexp}')")
23+
private String aktørId;
24+
25+
public ForeldrepengerPipAktørId(Long aktørId) {
26+
Objects.requireNonNull(aktørId, "aktørId");
27+
this.aktørId = validateAktørId(aktørId.toString());
28+
}
29+
30+
public ForeldrepengerPipAktørId(String aktørId) {
31+
this.aktørId = validateAktørId(aktørId);
32+
}
33+
34+
private String validateAktørId(String aktørId) {
35+
Objects.requireNonNull(aktørId, "aktørId");
36+
if (!VALID.matcher(aktørId).matches()) {
37+
// skal ikke skje, funksjonelle feilmeldinger håndteres ikke her.
38+
throw new IllegalArgumentException("Ugyldig aktørId '" + aktørId + "', tillatt pattern: " + VALID_REGEXP);
39+
}
40+
return aktørId;
41+
}
42+
43+
public String getVerdi() {
44+
return aktørId;
45+
}
46+
47+
@Override
48+
public boolean equals(Object obj) {
49+
return obj instanceof ForeldrepengerPipAktørId annen && Objects.equals(aktørId, annen.aktørId);
50+
}
51+
52+
@Override
53+
public int hashCode() {
54+
return Objects.hash(aktørId);
55+
}
56+
57+
@Override
58+
public String toString() {
59+
return getClass().getSimpleName() + "<maskert>";
60+
}
61+
62+
@Override
63+
public int compareTo(ForeldrepengerPipAktørId o) {
64+
// TODO: Burde ikke finnes
65+
return aktørId.compareTo(o.aktørId);
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package no.nav.vedtak.felles.integrasjon.pdlpip;
2+
3+
import java.net.URI;
4+
import java.time.Duration;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import jakarta.ws.rs.core.UriBuilder;
9+
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
import no.nav.vedtak.felles.integrasjon.rest.RestClient;
14+
import no.nav.vedtak.felles.integrasjon.rest.RestConfig;
15+
import no.nav.vedtak.felles.integrasjon.rest.RestRequest;
16+
17+
/*
18+
* Informasjon fra PDL til bruk kun for tilgangskontroll. Registrer klientapps hos pdl
19+
*
20+
* PROD: SD innenfor FSS ellers https pdl-pip-api.intern.nav.no (scope: prod-fss:pdl:pdl-pip-api)
21+
* DEV: SD innenfor FSS ellers https pdl-pip-api.dev.intern.nav.no (scope: dev-fss:pdl:pdl-pip-api)
22+
*/
23+
24+
// Extend og annoter med endpoint+default og scopes/default + tokenConfig = AzureAD_CC
25+
//@RestClientConfig(tokenConfig = TokenFlow.AZUREAD_CC, endpointProperty = "pdl.pip.base.url",
26+
// endpointDefault = "http://pdl-pip-api.pdl/api/v1", // For FSS - apps i GCP bruker https://pdl-pip-api.intern.nav.no/api/v1
27+
// scopesProperty = "pdl.pip.scope", scopesDefault = "api://prod-fss:pdl:pdl-pip-api/.default")
28+
public abstract class AbstractPersondataPipKlient implements PersondataPip {
29+
30+
private static final Logger LOG = LoggerFactory.getLogger(AbstractPersondataPipKlient.class);
31+
private static final String PERSON_PATH = "person";
32+
private static final String PERSON_BOLK_PATH = "personBolk";
33+
34+
private final RestClient client;
35+
private final RestConfig restConfig;
36+
private final URI pipPersonBolkEndpoint;
37+
private final URI pipPersonEndpoint;
38+
39+
40+
protected AbstractPersondataPipKlient() {
41+
this(RestClient.client());
42+
}
43+
44+
protected AbstractPersondataPipKlient(RestClient restClient) {
45+
this.client = restClient;
46+
this.restConfig = RestConfig.forClient(this.getClass());
47+
this.pipPersonEndpoint = UriBuilder.fromUri(restConfig.endpoint()).path(PERSON_PATH).build();
48+
this.pipPersonBolkEndpoint = UriBuilder.fromUri(restConfig.endpoint()).path(PERSON_BOLK_PATH).build();
49+
if (!restConfig.tokenConfig().isAzureAD()) {
50+
throw new IllegalArgumentException("Utviklerfeil: klient må annoteres med Azure CC");
51+
}
52+
}
53+
54+
@Override
55+
public PersondataPipDto hentTilgangPersondata(String ident) {
56+
var request = RestRequest.newGET(pipPersonEndpoint, restConfig)
57+
.header("ident", ident)
58+
.timeout(Duration.ofSeconds(5));
59+
try {
60+
return client.send(request, PersondataPipDto.class);
61+
} catch (Exception e) {
62+
LOG.info("PdlPip fikk feil", e);
63+
}
64+
return client.send(request, PersondataPipDto.class);
65+
}
66+
67+
@Override
68+
public Map<String, PersondataPipDto> hentTilgangPersondataBolk(List<String> identer) {
69+
var request = RestRequest.newPOSTJson(identer, pipPersonBolkEndpoint, restConfig)
70+
.timeout(Duration.ofSeconds(5));
71+
try {
72+
return client.sendReturnMap(request, PersondataPipDto.class);
73+
} catch (Exception e) {
74+
LOG.info("PdlPip fikk feil", e);
75+
}
76+
return client.sendReturnMap(request, PersondataPipDto.class);
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package no.nav.vedtak.felles.integrasjon.pdlpip;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
public interface PersondataPip {
7+
8+
PersondataPipDto hentTilgangPersondata(String ident);
9+
10+
Map<String, PersondataPipDto> hentTilgangPersondataBolk(List<String> identer);
11+
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package no.nav.vedtak.felles.integrasjon.pdlpip;
2+
3+
import java.time.LocalDate;
4+
import java.util.List;
5+
import java.util.Optional;
6+
7+
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
8+
9+
public record PersondataPipDto(String aktoerId, Person person, Identer identer, GeografiskTilknytning geografiskTilknytning) {
10+
11+
public record Person(List<Adressebeskyttelse> adressebeskyttelse, List<Fødsel> foedsel,
12+
List<Dødsfall> doedsfall, List<Familierelasjon> familierelasjoner) {
13+
}
14+
15+
public record Adressebeskyttelse(Gradering gradering) { }
16+
17+
public record Fødsel(LocalDate foedselsdato) { }
18+
19+
public record Dødsfall(LocalDate doedsdato) { }
20+
21+
public record Familierelasjon(String relatertPersonsIdent) { } // en personIdent (FNR/DNR)
22+
23+
public record Identer(List<Ident> identer) { }
24+
25+
public record Ident(String ident, Boolean historisk, IdentGruppe gruppe) { }
26+
27+
public record GeografiskTilknytning(GtType gtType, String gtKommune, String gtBydel, String gtLand, String regel) { }
28+
29+
public enum Gradering { STRENGT_FORTROLIG_UTLAND, STRENGT_FORTROLIG, FORTROLIG, @JsonEnumDefaultValue UDEFINERT }
30+
31+
public enum IdentGruppe { AKTORID, FOLKEREGISTERIDENT, NPID, @JsonEnumDefaultValue UDEFINERT }
32+
33+
public enum GtType { KOMMUNE, BYDEL, UTLAND, @JsonEnumDefaultValue UDEFINERT }
34+
35+
public enum Relasjonsrolle { FAR, MOR, MEDMOR, BARN, @JsonEnumDefaultValue UDEFINERT }
36+
37+
public boolean harStrengAdresseBeskyttelse() {
38+
return Optional.ofNullable(person()).map(Person::adressebeskyttelse).orElse(List.of()).stream()
39+
.map(Adressebeskyttelse::gradering)
40+
.anyMatch(g -> Gradering.STRENGT_FORTROLIG.equals(g) || Gradering.STRENGT_FORTROLIG_UTLAND.equals(g));
41+
}
42+
43+
public boolean harAdresseBeskyttelse() {
44+
return Optional.ofNullable(person()).map(Person::adressebeskyttelse).orElse(List.of()).stream()
45+
.map(Adressebeskyttelse::gradering)
46+
.anyMatch(g -> g != null && !Gradering.UDEFINERT.equals(g));
47+
}
48+
49+
public boolean erIkkeMyndig() {
50+
return Optional.ofNullable(person()).map(Person::foedsel).orElse(List.of()).stream()
51+
.map(Fødsel::foedselsdato)
52+
.anyMatch(f -> f == null || f.plusYears(18).isAfter(LocalDate.now()));
53+
}
54+
55+
public String personIdent() {
56+
return Optional.ofNullable(identer()).map(Identer::identer).orElse(List.of()).stream()
57+
.filter(i -> IdentGruppe.FOLKEREGISTERIDENT.equals(i.gruppe()))
58+
.filter(i -> !i.historisk())
59+
.map(Ident::ident)
60+
.findFirst().orElse(null);
61+
}
62+
63+
public List<String> personIdenter() {
64+
return Optional.ofNullable(identer()).map(Identer::identer).orElse(List.of()).stream()
65+
.filter(i -> IdentGruppe.FOLKEREGISTERIDENT.equals(i.gruppe()))
66+
.map(Ident::ident)
67+
.toList();
68+
}
69+
70+
public String aktørId() {
71+
return Optional.ofNullable(identer()).map(Identer::identer).orElse(List.of()).stream()
72+
.filter(i -> IdentGruppe.AKTORID.equals(i.gruppe()))
73+
.filter(i -> !i.historisk())
74+
.map(Ident::ident)
75+
.findFirst().orElse(null);
76+
}
77+
78+
public List<String> aktørIdMedHistoriske() {
79+
return Optional.ofNullable(identer()).map(Identer::identer).orElse(List.of()).stream()
80+
.filter(i -> IdentGruppe.AKTORID.equals(i.gruppe()))
81+
.map(Ident::ident)
82+
.toList();
83+
}
84+
85+
public boolean harNasjonalTilknytning() {
86+
return Optional.ofNullable(geografiskTilknytning()).map(GeografiskTilknytning::gtType)
87+
.filter(gtt -> GtType.KOMMUNE.equals(gtt) || GtType.BYDEL.equals(gtt))
88+
.isPresent();
89+
}
90+
91+
public boolean harIkkeNasjonalTilknytning() {
92+
return Optional.ofNullable(geografiskTilknytning()).map(GeografiskTilknytning::gtType)
93+
.filter(gtt -> GtType.KOMMUNE.equals(gtt) || GtType.BYDEL.equals(gtt))
94+
.isEmpty();
95+
}
96+
97+
}

0 commit comments

Comments
 (0)