Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/levende-arbeidsforhold-ansettelse
Browse files Browse the repository at this point in the history
  • Loading branch information
rfc3092 committed Oct 26, 2024
2 parents b57f414 + 2bc7711 commit 6a116e8
Show file tree
Hide file tree
Showing 142 changed files with 3,113 additions and 1,179 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/proxy.fullmakt-proxy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: fullmakt-proxy

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

jobs:
workflow:
uses: ./.github/workflows/common.workflow.backend.yml
with:
cluster: "dev-fss"
working-directory: "proxies/fullmakt-proxy"
deploy-tag: "#deploy-proxy-fullmakt"
permissions:
contents: read
id-token: write
secrets: inherit
6 changes: 4 additions & 2 deletions apps/budpro-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
FROM ghcr.io/navikt/baseimages/temurin:21
LABEL maintainer="Team Dolly"

ADD build/libs/app.jar /app/app.jar
COPY build/libs/app.jar /app/app.jar

ENV JAVA_OPTS="-Dspring.profiles.active=prod"
RUN wget -q https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz -P /app/agent && tar xzf /app/agent/profiler_java_agent.tar.gz -C /app/agent && rm /app/agent/profiler_java_agent.tar.gz

ENV JAVA_OPTS="-Dspring.profiles.active=prod -agentpath:/app/agent/profiler_java_agent.so=-cprof_project_id=dolly-dev-ff83,-cprof_service=testnav-budpro-service,-cprof_enable_heap_sampling=true,-logtostderr,-minloglevel=1"

EXPOSE 8080
8 changes: 7 additions & 1 deletion apps/budpro-service/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,10 @@ spec:
path: "/internal/health/readiness"
replicas:
min: 1
max: 1
max: 1
gcp:
permissions:
- resource:
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
kind: Project
role: roles/cloudprofiler.agent
2 changes: 1 addition & 1 deletion apps/dolly-backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ https://dolly-backend.intern.dev.nav.no/swagger-ui.html
## Kjør lokalt
* Se [generell informasjon](../../docs/local_general.md).
* Applikasjonen er avhengig av en database i GCP, se [egen dokumentasjon](../../docs/gcp_db.md).
* Applikasjonen er avhengig av Elasticsearch:
* Applikasjonen er avhengig av OpenSearch:
```aiexclude
> docker run -p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" -e "plugins.security.disabled=true" -e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=YLAgOm}rz#o6#Aq" --name opensearch -d opensearchproject/opensearch:latest
```
Expand Down
1 change: 1 addition & 0 deletions apps/dolly-backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies {
implementation 'no.nav.testnav.libs:data-transfer-objects'
implementation 'no.nav.testnav.libs:data-transfer-search-objects'
implementation 'no.nav.testnav.libs:reactive-core'
implementation 'no.nav.testnav.libs:vault'

implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:$versions.springdoc"
implementation "io.swagger.core.v3:swagger-annotations-jakarta:$versions.swagger"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static boolean isEqualArbeidsforhold(Arbeidsforhold response, Arbeidsforh

return (isArbeidsgiverOrganisasjonAlike(response, request) ||
isArbeidsgiverPersonAlike(response, request)) &&
response.getType().equals(request.getType());
response.getArbeidsforholdId().equals(request.getArbeidsforholdId());
}

public static ArbeidsforholdEksistens doEksistenssjekk(ArbeidsforholdRespons response,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package no.nav.dolly.bestilling.fullmakt;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.dolly.bestilling.ClientFuture;
import no.nav.dolly.bestilling.ClientRegister;
import no.nav.dolly.bestilling.fullmakt.dto.FullmaktResponse;
import no.nav.dolly.bestilling.pdldata.PdlDataConsumer;
import no.nav.dolly.domain.jpa.BestillingProgress;
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.util.TransactionHelperService;
import no.nav.testnav.libs.data.pdlforvalter.v1.PersonDTO;
import no.nav.testnav.libs.data.pdlforvalter.v1.RelasjonType;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

import static java.util.Objects.isNull;
import static no.nav.dolly.errorhandling.ErrorStatusDecoder.getInfoVenter;
import static org.apache.http.util.TextUtils.isBlank;

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

private static final String FULLMAKT_REPRESENTASJON = "FULLMAKT_REPR#";

private final ErrorStatusDecoder errorStatusDecoder;
private final TransactionHelperService transactionHelperService;
private final FullmaktConsumer fullmaktConsumer;
private final PdlDataConsumer pdlDataConsumer;

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

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

return Flux.fromIterable(bestilling.getFullmakt())
.doOnNext(ordre ->
transactionHelperService.persister(progress, BestillingProgress::setFullmaktStatus,
getInfoVenter("Fullmakt (Representasjon)")))
.flatMap(fullmakt -> {
fullmakt.setFullmaktsgiver(dollyPerson.getIdent());
if (isBlank(fullmakt.getFullmektig())) {
return pdlDataConsumer.getPersoner(List.of(dollyPerson.getIdent()))
.flatMap(person -> Flux.fromIterable(person.getRelasjoner())
.filter(relasjon -> relasjon.getRelasjonType().equals(RelasjonType.FULLMEKTIG)))
.next()
.map(relasjon -> {
fullmakt.setFullmektigsNavn(getFullName(relasjon.getRelatertPerson()));
fullmakt.setFullmektig(relasjon.getRelatertPerson().getIdent());
return fullmakt;
});
} else {
return Mono.just(fullmakt);
}
})
.collectList()
.flatMapMany(fullmakter -> fullmaktConsumer.createFullmaktData(fullmakter, dollyPerson.getIdent()))
.map(this::getStatus)
.map(status -> futurePersist(progress, status));
}

return Flux.empty();
}

@Override
public void release(List<String> identer) {

identer.forEach(ident -> fullmaktConsumer.getFullmaktData(List.of(ident)).subscribe(
fullmakter -> fullmakter.getFullmakt()
.forEach(fullmakt -> fullmaktConsumer
.deleteFullmaktData(ident, fullmakt.getFullmaktId()).subscribe())));
}

private ClientFuture futurePersist(BestillingProgress progress, String status) {

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

private String getStatus(FullmaktResponse response) {

return isNull(response.getStatus()) ? "OK" :
errorStatusDecoder.getErrorText(response.getStatus(), response.getMelding());
}

private String getFullName(PersonDTO person) {
var navn = person.getNavn().getFirst();
return (isBlank(navn.getMellomnavn()))
? "%s %s".formatted(navn.getFornavn(), navn.getEtternavn())
: "%s %s %s".formatted(navn.getFornavn(), navn.getMellomnavn(), navn.getEtternavn());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package no.nav.dolly.bestilling.fullmakt;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import no.nav.dolly.bestilling.ConsumerStatus;
import no.nav.dolly.bestilling.fullmakt.command.DeleteFullmaktDataCommand;
import no.nav.dolly.bestilling.fullmakt.command.GetFullmaktDataCommand;
import no.nav.dolly.bestilling.fullmakt.command.PostFullmaktDataCommand;
import no.nav.dolly.bestilling.fullmakt.dto.FullmaktResponse;
import no.nav.dolly.config.Consumers;
import no.nav.dolly.domain.resultset.fullmakt.RsFullmakt;
import no.nav.dolly.metrics.Timed;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.List;

import static no.nav.dolly.util.JacksonExchangeStrategyUtil.getJacksonStrategy;

@Slf4j
@Service
public class FullmaktConsumer implements ConsumerStatus {

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

public FullmaktConsumer(
TokenExchange tokenService,
Consumers consumers,
ObjectMapper objectMapper,
WebClient.Builder webClientBuilder
) {
this.tokenService = tokenService;
serverProperties = consumers.getTestnavFullmaktProxy();
this.webClient = webClientBuilder
.baseUrl(serverProperties.getUrl())
.exchangeStrategies(getJacksonStrategy(objectMapper))
.build();
}

@Timed(name = "providers", tags = { "operation", "fullmakt_createData" })
public Flux<FullmaktResponse> createFullmaktData(List<RsFullmakt> fullmakter, String ident) {

log.info("Fullmakt opprett {}", fullmakter);
return tokenService.exchange(serverProperties)
.flatMapMany(token ->
Flux.range(0, fullmakter.size())
.delayElements(Duration.ofMillis(100))
.flatMap(idx -> new PostFullmaktDataCommand(webClient, token.getTokenValue(), ident, fullmakter.get(idx)).call()));
}

@Timed(name = "providers", tags = { "operation", "fullmakt_getData" })
public Flux<FullmaktResponse> getFullmaktData(List<String> identer) {

return tokenService.exchange(serverProperties)
.flatMapMany(token -> Flux.range(0, identer.size())
.delayElements(Duration.ofMillis(50))
.flatMap(idx -> new GetFullmaktDataCommand(webClient, identer.get(idx),
token.getTokenValue()).call()));
}

@Timed(name = "providers", tags = { "operation", "fullmakt_getData" })
public Mono<ResponseEntity<Void>> deleteFullmaktData(String ident, Integer fullmaktId) {

return tokenService.exchange(serverProperties)
.flatMap(token -> new DeleteFullmaktDataCommand(webClient, ident, fullmaktId,
token.getTokenValue()).call());
}

@Override
public String serviceUrl() {
return serverProperties.getUrl();
}

@Override
public String consumerName() {
return "testnav-fullmakt-proxy";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package no.nav.dolly.bestilling.fullmakt.command;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.dolly.util.RequestHeaderUtil;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import no.nav.testnav.libs.securitycore.config.UserConstant;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
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;

import static no.nav.dolly.domain.CommonKeysAndUtils.CONSUMER;
import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CALL_ID;
import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID;
import static no.nav.dolly.util.TokenXUtil.getUserJwt;

@Slf4j
@RequiredArgsConstructor
public class DeleteFullmaktDataCommand implements Callable<Mono<ResponseEntity<Void>>> {

private static final String DELETE_FULLMAKT_URL = "/api/fullmakt/{fullmaktId}";

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

public Mono<ResponseEntity<Void>> call() {

return webClient.get()
.uri(uriBuilder -> uriBuilder
.path(DELETE_FULLMAKT_URL)
.build(fullmaktId))
.header(HEADER_NAV_CALL_ID, RequestHeaderUtil.getNavCallId())
.header(HEADER_NAV_CONSUMER_ID, CONSUMER)
.header("fnr", ident)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.header(UserConstant.USER_HEADER_JWT, getUserJwt())
.retrieve()
.toBodilessEntity()
.doOnError(WebClientFilter::logErrorMessage)
.doOnSuccess(response -> log.info("Fullmakt with id {} deleted for person with ident {}", fullmaktId, ident))
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException))
.doOnError(WebClientFilter::logErrorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package no.nav.dolly.bestilling.fullmakt.command;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.dolly.bestilling.fullmakt.dto.FullmaktResponse;
import no.nav.dolly.util.RequestHeaderUtil;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import no.nav.testnav.libs.securitycore.config.UserConstant;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.util.retry.Retry;

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

import static no.nav.dolly.domain.CommonKeysAndUtils.CONSUMER;
import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CALL_ID;
import static no.nav.dolly.domain.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID;
import static no.nav.dolly.util.TokenXUtil.getUserJwt;

@Slf4j
@RequiredArgsConstructor
public class GetFullmaktDataCommand implements Callable<Flux<FullmaktResponse>> {

private static final String HENT_FULLMAKT_URL = "/api/fullmektig";

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

public Flux<FullmaktResponse> call() {

return webClient.get()
.uri(uriBuilder -> uriBuilder
.path(HENT_FULLMAKT_URL)
.build())
.header(HEADER_NAV_CALL_ID, RequestHeaderUtil.getNavCallId())
.header(HEADER_NAV_CONSUMER_ID, CONSUMER)
.header("fnr", ident)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.header(UserConstant.USER_HEADER_JWT, getUserJwt())
.retrieve()
.bodyToFlux(FullmaktResponse.class)
.doOnError(WebClientFilter::logErrorMessage)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException))
.doOnError(WebClientFilter::logErrorMessage);
}
}
Loading

0 comments on commit 6a116e8

Please sign in to comment.