Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/idporten-cors
Browse files Browse the repository at this point in the history
  • Loading branch information
krharum authored Oct 15, 2024
2 parents fe98e52 + 1a587c6 commit c7f2563
Show file tree
Hide file tree
Showing 62 changed files with 1,623 additions and 41 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/proxy.yrkesskade-proxy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: yrkesskade-proxy

on:
push:
paths:
- plugins/**
- libs/reactive-core/**
- libs/reactive-proxy/**
- libs/reactive-security/**
- libs/security-core/**
- proxies/yrkesskade-proxy/**
- .github/workflows/proxy.yrkesskade-proxy.yml

jobs:
workflow:
uses: ./.github/workflows/common.workflow.backend.yml
with:
cluster: "dev-gcp"
working-directory: "proxies/yrkesskade-proxy"
deploy-tag: "#deploy-proxy-yrkesskade"
permissions:
contents: read
id-token: write
secrets: inherit
1 change: 1 addition & 0 deletions apps/dolly-backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
implementation 'no.nav.testnav.libs:servlet-insecure-security'
implementation 'no.nav.testnav.libs:security-core'
implementation 'no.nav.testnav.libs:database'
implementation 'no.nav.testnav.libs:vault'
implementation 'no.nav.testnav.libs:data-transfer-objects'
implementation 'no.nav.testnav.libs:data-transfer-search-objects'
implementation 'no.nav.testnav.libs:reactive-core'
Expand Down
1 change: 1 addition & 0 deletions apps/dolly-backend/config.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ spec:
- application: testnav-sykemelding-api
- application: testnav-synt-sykemelding-api
- application: testnav-tps-messaging-service
- application: testnav-yrkesskade-proxy
- application: testnorge-profil-api-dev
external:
- host: testnav-arena-forvalteren-proxy.dev-fss-pub.nais.io
Expand Down
1 change: 1 addition & 0 deletions apps/dolly-backend/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ spec:
- application: testnav-synt-sykemelding-api
- application: testnav-tps-messaging-service
- application: testnorge-profil-api
- application: testnav-yrkesskade-proxy
external:
- host: testnav-arena-forvalteren-proxy.dev-fss-pub.nais.io
- host: testnav-brregstub-proxy.dev-fss-pub.nais.io
Expand Down
1 change: 1 addition & 0 deletions apps/dolly-backend/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ includeBuild '../../.github/workflows'
includeBuild '../../libs/data-transfer-objects'
includeBuild '../../libs/data-transfer-search-objects'
includeBuild '../../libs/database'
includeBuild '../../libs/vault'
includeBuild '../../libs/reactive-core'
includeBuild '../../libs/security-core'
includeBuild '../../libs/servlet-core'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ private Flux<Map.Entry<String, Set<String>>> getIdentWithRelasjoner(DollyPerson
.map(PdlPerson.ForelderBarnRelasjon::getRelatertPersonsIdent)
.filter(Objects::nonNull),
person.getPerson().getFullmakt().stream()
.map(FullmaktDTO::getMotpartsPersonident))
.map(FullmaktDTO::getMotpartsPersonident),
person.getPerson().getVergemaalEllerFremtidsfullmakt().stream()
.map(PdlPerson.Vergemaal::getVergeEllerFullmektig)
.map(PdlPerson.VergeEllerFullmektig::getMotpartsPersonident)
.filter(Objects::nonNull))
.flatMap(Function.identity())))
.map(ident -> Map.entry(ident, new HashSet<>())));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package no.nav.dolly.bestilling.yrkesskade;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import no.nav.dolly.bestilling.ClientFuture;
import no.nav.dolly.bestilling.ClientRegister;
import no.nav.dolly.bestilling.personservice.PersonServiceConsumer;
import no.nav.dolly.bestilling.yrkesskade.dto.ResponseDTO;
import no.nav.dolly.bestilling.yrkesskade.dto.ResponseDTO.Status;
import no.nav.dolly.bestilling.yrkesskade.dto.YrkesskadeResponseDTO;
import no.nav.dolly.domain.jpa.BestillingProgress;
import no.nav.dolly.domain.jpa.TransaksjonMapping;
import no.nav.dolly.domain.resultset.RsDollyUtvidetBestilling;
import no.nav.dolly.domain.resultset.dolly.DollyPerson;
import no.nav.dolly.errorhandling.ErrorStatusDecoder;
import no.nav.dolly.mapper.MappingContextUtils;
import no.nav.dolly.service.TransaksjonMappingService;
import no.nav.dolly.util.TransactionHelperService;
import no.nav.testnav.libs.dto.yrkesskade.v1.YrkesskadeRequest;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static java.lang.Boolean.TRUE;
import static no.nav.dolly.domain.resultset.SystemTyper.YRKESSKADE;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

@Slf4j
@Service
@RequiredArgsConstructor
public class YrkesskadeClient implements ClientRegister {

private final MapperFacade mapper;
private final ObjectMapper objectMapper;
private final YrkesskadeConsumer yrkesskadeConsumer;
private final TransactionHelperService transactionHelperService;
private final TransaksjonMappingService transaksjonMappingService;
private final PersonServiceConsumer personServiceConsumer;

@Override
public Flux<ClientFuture> gjenopprett(RsDollyUtvidetBestilling bestilling, DollyPerson dollyPerson, BestillingProgress progress, boolean isOpprettEndre) {

if (!bestilling.getYrkesskader().isEmpty()) {

var index = new AtomicInteger(0);
transactionHelperService.persister(progress, BestillingProgress::getYrkesskadeStatus,
BestillingProgress::setYrkesskadeStatus, "Yrkesskade#1:%s".formatted(ErrorStatusDecoder.getInfoVenter(
YRKESSKADE.getBeskrivelse())));

return Flux.from(yrkesskadeConsumer.hentSaksoversikt(dollyPerson.getIdent())
.map(resultat -> !resultat.getSaker().isEmpty())
.map(eksisterendeSak -> !eksisterendeSak || isOpprettEndre)
.flatMap(nysak -> TRUE.equals(nysak) ?
personServiceConsumer.getPdlPersoner(List.of(dollyPerson.getIdent()))
.doOnNext(personBolk -> log.info("Hentet pdlPersonBolk"))
.flatMap(personbolk -> Flux.fromIterable(bestilling.getYrkesskader())
.map(yrkesskade -> {
var context = MappingContextUtils.getMappingContext();
context.setProperty("ident", dollyPerson.getIdent());
context.setProperty("personBolk", personbolk);
return mapper.map(yrkesskade, YrkesskadeRequest.class, context);
})
.map(yrkesskade -> yrkesskadeConsumer.lagreYrkesskade(yrkesskade)
.map(status -> lagreTransaksjon(status, yrkesskade, progress.getBestilling().getId()))))
.flatMap(Flux::from)
.map(status -> encodeStatus(status, index.incrementAndGet()))
.collectList()
.map(resultat -> futurePersist(progress, resultat)) :

Mono.just(futurePersist(progress, List.of(ResponseDTO.builder()
.id(index.incrementAndGet())
.status(Status.OK)
.build())))
));
}

return Flux.empty();
}

@Override
public void release(List<String> identer) {
// Er ikke støttet
}

private ResponseDTO encodeStatus(YrkesskadeResponseDTO status, int index) {

String melding;

if (status.getStatus().is2xxSuccessful()) {
melding = null;
} else if (isNotBlank(status.getMelding())) {
melding = status.getMelding();
} else {
melding = status.getStatus().toString();
}

return ResponseDTO.builder()
.id(index)
.status(status.getStatus().is2xxSuccessful() ? Status.OK : Status.FEIL)
.melding(melding)
.build();
}

private ClientFuture futurePersist(BestillingProgress progress, String status) {

return () -> {
transactionHelperService.persister(progress, BestillingProgress::setYrkesskadeStatus, status);
return progress;
};
}

private ClientFuture futurePersist(BestillingProgress progress, List<ResponseDTO> response) {

return futurePersist(progress, response.stream()
.map(entry -> "Yrkesskade#%d:%s".formatted(entry.getId(),
entry.getStatus() == Status.OK ? "OK" :
ErrorStatusDecoder.encodeStatus("FEIL: %s".formatted(entry.getMelding()))))
.collect(Collectors.joining(",")));
}

private YrkesskadeResponseDTO lagreTransaksjon(YrkesskadeResponseDTO status, YrkesskadeRequest request,
Long bestillingId) {

if (status.getStatus().is2xxSuccessful()) {
transaksjonMappingService.save(TransaksjonMapping.builder()
.bestillingId(bestillingId)
.transaksjonId(toJson(request))
.ident(request.getSkadelidtIdentifikator())
.datoEndret(LocalDateTime.now())
.system(YRKESSKADE.name())
.build());
}
return status;
}

private String toJson(Object object) {

try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
log.error("Feilet å konvertere transaksjonsId for dokarkiv", e);
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package no.nav.dolly.bestilling.yrkesskade;

import lombok.extern.slf4j.Slf4j;
import no.nav.dolly.bestilling.yrkesskade.command.YrkesskadeGetCommand;
import no.nav.dolly.bestilling.yrkesskade.command.YrkesskadePostCommand;
import no.nav.dolly.bestilling.yrkesskade.dto.SaksoversiktDTO;
import no.nav.dolly.bestilling.yrkesskade.dto.YrkesskadeResponseDTO;
import no.nav.dolly.config.Consumers;
import no.nav.testnav.libs.dto.yrkesskade.v1.YrkesskadeRequest;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Slf4j
@Service
public class YrkesskadeConsumer {

private final WebClient webClient;
private final TokenExchange tokenExchange;
private final ServerProperties serverProperties;

public YrkesskadeConsumer(
TokenExchange tokenExchange,
Consumers consumers,
WebClient.Builder webClientBuilder) {

this.tokenExchange = tokenExchange;
serverProperties = consumers.getYrkesskadeProxy();
this.webClient = webClientBuilder
.baseUrl(serverProperties.getUrl())
.build();
}

public Mono<YrkesskadeResponseDTO> lagreYrkesskade(YrkesskadeRequest request) {

log.info("Sender yrkesskade melding: {}", request);
return tokenExchange.exchange(serverProperties)
.flatMap(token -> new YrkesskadePostCommand(webClient, request, token.getTokenValue()).call())
.doOnNext(response ->
log.info("Mottatt response fra yrkesskade service {}", response));
}

public Mono<SaksoversiktDTO> hentSaksoversikt(String ident) {

log.info("Henter yrkeskade saksoversikt for ident {}", ident);
return tokenExchange.exchange(serverProperties)
.flatMap(token -> new YrkesskadeGetCommand(webClient, ident, token.getTokenValue()).call())
.doOnNext(response ->
log.info("Mottatt saksoversikt fra yrkesskade service {}", response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package no.nav.dolly.bestilling.yrkesskade.command;

import lombok.RequiredArgsConstructor;
import no.nav.dolly.bestilling.yrkesskade.dto.SaksoversiktDTO;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

import java.time.Duration;
import java.util.concurrent.Callable;

@RequiredArgsConstructor
public class YrkesskadeGetCommand implements Callable<Mono<SaksoversiktDTO>> {

private static final String YRKESSKADE_URL = "/api/v1/yrkesskader/{ident}";

private final WebClient webClient;
private final String ident;
private final String token;

@Override
public Mono<SaksoversiktDTO> call() {

return webClient
.get()
.uri(uriBuilder -> uriBuilder.path(YRKESSKADE_URL)
.build(ident))
.accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.header("ident", ident)
.retrieve()
.bodyToMono(SaksoversiktDTO.class)
.map(resultat -> SaksoversiktDTO.builder()
.status(HttpStatusCode.valueOf(200))
.saker(resultat.getSaker())
.build())
.doOnError(WebClientFilter::logErrorMessage)
.onErrorResume(throwable -> Mono.just(SaksoversiktDTO.builder()
.status(WebClientFilter.getStatus(throwable))
.melding(WebClientFilter.getMessage(throwable))
.build()))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package no.nav.dolly.bestilling.yrkesskade.command;

import lombok.RequiredArgsConstructor;
import no.nav.dolly.bestilling.yrkesskade.dto.YrkesskadeResponseDTO;
import no.nav.testnav.libs.dto.yrkesskade.v1.YrkesskadeRequest;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

import java.time.Duration;
import java.util.concurrent.Callable;

@RequiredArgsConstructor
public class YrkesskadePostCommand implements Callable<Mono<YrkesskadeResponseDTO>> {

private static final String YRKESSKADE_URL = "/api/v1/yrkesskader";

private final WebClient webClient;
private final YrkesskadeRequest yrkesskadeRequest;
private final String token;

@Override
public Mono<YrkesskadeResponseDTO> call() {

return webClient
.post()
.uri(uriBuilder -> uriBuilder.path(YRKESSKADE_URL).build())
.accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.header("ident", yrkesskadeRequest.getInnmelderIdentifikator())
.bodyValue(yrkesskadeRequest)
.retrieve()
.toBodilessEntity()
.map(response -> YrkesskadeResponseDTO.builder()
.status(HttpStatusCode.valueOf(201))
.build())
.doOnError(WebClientFilter::logErrorMessage)
.onErrorResume(throwable -> Mono.just(YrkesskadeResponseDTO.builder()
.status(WebClientFilter.getStatus(throwable))
.melding(WebClientFilter.getMessage(throwable))
.build()))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.nav.dolly.bestilling.yrkesskade.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResponseDTO {

public enum Status {OK, FEIL}

private Integer id;
private Status status;
private String melding;
}
Loading

0 comments on commit c7f2563

Please sign in to comment.