diff --git a/apps/levende-arbeidsforhold-ansettelse/99-dolly-convert-to-pk8.sh b/apps/levende-arbeidsforhold-ansettelse/99-dolly-convert-to-pk8.sh new file mode 100644 index 00000000000..49cfce0b64e --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/99-dolly-convert-to-pk8.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +# +# Converts NAIS provided key.pem to PKCS#8 PEM format, which can be used by R2dbc. +# +openssl pkey -in /var/run/secrets/nais.io/sqlcertificate/key.pem -out /tmp/pk8.pem \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/Dockerfile b/apps/levende-arbeidsforhold-ansettelse/Dockerfile index dd8161548f8..da2ab16eeb7 100644 --- a/apps/levende-arbeidsforhold-ansettelse/Dockerfile +++ b/apps/levende-arbeidsforhold-ansettelse/Dockerfile @@ -3,6 +3,7 @@ LABEL maintainer="Team Dolly" ENV JAVA_OPTS="-Dspring.profiles.active=prod" -ADD /build/libs/app.jar /app/app.jar +COPY 99-dolly-convert-to-pk8.sh /init-scripts/ +COPY /build/libs/app.jar /app/ EXPOSE 8080 \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/build.gradle b/apps/levende-arbeidsforhold-ansettelse/build.gradle index 90dcde18837..e0037afe5c5 100644 --- a/apps/levende-arbeidsforhold-ansettelse/build.gradle +++ b/apps/levende-arbeidsforhold-ansettelse/build.gradle @@ -2,57 +2,36 @@ plugins { id "dolly-apps" } -test { - useJUnitPlatform() -} - sonarqube { properties { - property "sonar.dynamicAnalysis", "reuseReports" - property "sonar.host.url", "https://sonarcloud.io" - property "sonar.java.coveragePlugin", "jacoco" - property "sonar.language", "java" - property "sonar.token", System.getenv("SONAR_TOKEN") - property "sonar.organization", "navikt" - property "sonar.project.monorepo.enabled", true property "sonar.projectKey", "testnav-levende-arbeidsforhold-ansettelse" property "sonar.projectName", "testnav-levende-arbeidsforhold-ansettelse" - property "sonar.sourceEncoding", "UTF-8" } } - dependencies { implementation "no.nav.testnav.libs:data-transfer-objects" implementation "no.nav.testnav.libs:data-transfer-search-objects" - implementation "no.nav.testnav.libs:database" implementation "no.nav.testnav.libs:reactive-core" implementation "no.nav.testnav.libs:security-core" - implementation "no.nav.testnav.libs:servlet-core" + implementation "no.nav.testnav.libs:reactive-security" implementation "no.nav.testnav.libs:servlet-insecure-security" implementation "no.nav.testnav.libs:vault" - implementation "org.springframework.boot:spring-boot-starter-oauth2-client" - implementation "org.springframework.boot:spring-boot-starter-data-jpa" + implementation "org.springframework.boot:spring-boot-starter-data-r2dbc" + implementation "org.springframework.boot:spring-boot-starter-oauth2-resource-server" + implementation "org.springframework.boot:spring-boot-starter-security" - implementation "org.springframework.cloud:spring-cloud-starter-vault-config" + implementation "org.flywaydb:flyway-core" + implementation "org.flywaydb:flyway-database-postgresql" - implementation "org.postgresql:postgresql:42.7.3" + runtimeOnly "org.postgresql:postgresql" + runtimeOnly "org.postgresql:r2dbc-postgresql" implementation "io.micrometer:micrometer-registry-prometheus" - implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0" - implementation "io.swagger.core.v3:swagger-annotations-jakarta:2.2.21" - - implementation "org.hibernate.validator:hibernate-validator" - - testImplementation "org.springframework.boot:spring-boot-starter-test" - testImplementation "org.springframework.cloud:spring-cloud-contract-wiremock" - - implementation "org.projectlombok:lombok" - annotationProcessor "org.projectlombok:lombok" - testAnnotationProcessor "org.projectlombok:lombok" - - implementation "com.zaxxer:HikariCP" - implementation "com.h2database:h2" + implementation "org.springdoc:springdoc-openapi-starter-webflux-ui:$versions.springdoc" + implementation "io.swagger.core.v3:swagger-annotations-jakarta:$versions.swagger" + + testRuntimeOnly "io.r2dbc:r2dbc-h2" } diff --git a/apps/levende-arbeidsforhold-ansettelse/config.yml b/apps/levende-arbeidsforhold-ansettelse/config.yml index 6d779e98ed4..4c3f2ab68c7 100644 --- a/apps/levende-arbeidsforhold-ansettelse/config.yml +++ b/apps/levende-arbeidsforhold-ansettelse/config.yml @@ -28,11 +28,6 @@ spec: allowAllUsers: true enabled: true tenant: nav.no - liveness: - path: /internal/isAlive - initialDelay: 4 - periodSeconds: 5 - failureThreshold: 500 observability: logging: destinations: @@ -40,11 +35,12 @@ spec: autoInstrumentation: enabled: true runtime: java + liveness: + initialDelay: 45 + path: /internal/health/liveness readiness: - path: /internal/isReady - initialDelay: 4 - periodSeconds: 5 - failureThreshold: 500 + initialDelay: 45 + path: /internal/health/readiness prometheus: enabled: true path: /internal/metrics diff --git a/apps/levende-arbeidsforhold-ansettelse/settings.gradle b/apps/levende-arbeidsforhold-ansettelse/settings.gradle index 7c8a740fb8c..bb179528ada 100644 --- a/apps/levende-arbeidsforhold-ansettelse/settings.gradle +++ b/apps/levende-arbeidsforhold-ansettelse/settings.gradle @@ -4,13 +4,12 @@ plugins { rootProject.name = 'levende-arbeidsforhold-ansettelse' -includeBuild '../../libs/security-core' -includeBuild '../../libs/servlet-core' +includeBuild '../../libs/reactive-security' includeBuild '../../libs/reactive-core' +includeBuild '../../libs/security-core' includeBuild '../../libs/servlet-insecure-security' includeBuild '../../libs/data-transfer-objects' includeBuild '../../libs/data-transfer-search-objects' -includeBuild '../../libs/database' includeBuild '../../libs/vault' develocity { diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java index af85ef82344..42c3411a5ef 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java @@ -1,12 +1,30 @@ package no.nav.testnav.levendearbeidsforholdansettelse; +import no.nav.testnav.libs.reactivecore.config.CoreConfig; +import no.nav.testnav.libs.reactivesecurity.config.SecureOAuth2ServerToServerConfiguration; +import no.nav.testnav.libs.standalone.servletsecurity.config.InsecureJwtServerToServerConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; +import org.springframework.data.r2dbc.config.EnableR2dbcAuditing; +import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.web.reactive.config.EnableWebFlux; @SpringBootApplication +@EnableAsync +@EnableR2dbcAuditing +@EnableR2dbcRepositories +@EnableWebFlux +@Import({ + CoreConfig.class, + SecureOAuth2ServerToServerConfiguration.class, + InsecureJwtServerToServerConfiguration.class +}) public class LevendeArbeidsforholdAnsettelseApplication { public static void main(String[] args) { SpringApplication.run(LevendeArbeidsforholdAnsettelseApplication.class, args); } + } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/ApplicationConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/ApplicationConfig.java deleted file mode 100644 index cdfc25cd18a..00000000000 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/ApplicationConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package no.nav.testnav.levendearbeidsforholdansettelse.config; - -import no.nav.testnav.libs.servletcore.config.ApplicationCoreConfig; -import no.nav.testnav.libs.standalone.servletsecurity.config.InsecureJwtServerToServerConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.scheduling.annotation.EnableAsync; - -@Configuration -@Import({ - ApplicationCoreConfig.class, - InsecureJwtServerToServerConfiguration.class -}) -@EnableAsync -public class ApplicationConfig { - -} - diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/OpenApiConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/OpenApiConfig.java index 366834bcc32..863b0003ff2 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/OpenApiConfig.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/OpenApiConfig.java @@ -7,16 +7,19 @@ import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; -import no.nav.testnav.libs.servletcore.config.ApplicationProperties; +import no.nav.testnav.libs.reactivecore.config.ApplicationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.http.HttpHeaders; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; import java.util.Arrays; @Configuration -public class OpenApiConfig implements WebMvcConfigurer { +public class OpenApiConfig implements WebFilter { @Bean public OpenAPI openApi(ApplicationProperties applicationProperties) { @@ -26,7 +29,7 @@ public OpenAPI openApi(ApplicationProperties applicationProperties) { .scheme("bearer") .bearerFormat("JWT") .in(SecurityScheme.In.HEADER) - .name("Authorization") + .name(HttpHeaders.AUTHORIZATION) )) .addSecurityItem( new SecurityRequirement().addList("bearer-jwt", Arrays.asList("read", "write"))) @@ -48,7 +51,15 @@ public OpenAPI openApi(ApplicationProperties applicationProperties) { } @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/swagger").setViewName("redirect:/swagger-ui.html"); + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + if (exchange.getRequest().getURI().getPath().equals("/swagger")) { + return chain + .filter(exchange.mutate() + .request(exchange.getRequest() + .mutate().path("/swagger-ui.html").build()) + .build()); + } + + return chain.filter(exchange); } } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/SecurityConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/SecurityConfig.java index 0f287cc8b54..9cbb0b2b1ba 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/SecurityConfig.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/SecurityConfig.java @@ -1,26 +1,28 @@ package no.nav.testnav.levendearbeidsforholdansettelse.config; +import lombok.RequiredArgsConstructor; +import no.nav.testnav.libs.reactivesecurity.manager.JwtReactiveAuthenticationManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; -@EnableWebSecurity @Configuration +@EnableWebFluxSecurity +@EnableReactiveMethodSecurity +@RequiredArgsConstructor public class SecurityConfig { + private final JwtReactiveAuthenticationManager jwtReactiveAuthenticationManager; + @Bean @SuppressWarnings("java:S4502") - public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { - - httpSecurity.sessionManagement(sessionConfig -> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .csrf(AbstractHttpConfigurer::disable) - .authorizeHttpRequests(authorizeConfig -> authorizeConfig.requestMatchers( + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity httpSecurity) { + return httpSecurity + .csrf(ServerHttpSecurity.CsrfSpec::disable) + .authorizeExchange(authorizeConfig -> authorizeConfig.pathMatchers( "/internal/**", "/webjars/**", "/swagger-resources/**", @@ -31,13 +33,8 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti "/swagger-ui.html", "/h2/**", "/member/**") - .permitAll() - .requestMatchers("/api/**") - .fullyAuthenticated()) - .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) - .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(Customizer.withDefaults())); - - return httpSecurity.build(); + .permitAll().anyExchange().authenticated()) + .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(jwtSpec -> jwtSpec.authenticationManager(jwtReactiveAuthenticationManager))) + .build(); } -} - +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/WebConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/WebConfig.java new file mode 100644 index 00000000000..e228460b2fc --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/config/WebConfig.java @@ -0,0 +1,15 @@ +package no.nav.testnav.levendearbeidsforholdansettelse.config; + +import no.nav.testnav.levendearbeidsforholdansettelse.utility.PageableHandlerMethodArgumentResolver; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.config.WebFluxConfigurer; +import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer; + +@Configuration +public class WebConfig implements WebFluxConfigurer { + + @Override + public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { + configurer.addCustomResolver(new PageableHandlerMethodArgumentResolver()); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/AaregConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/AaregConsumer.java index e921868112a..cd7b85d1df4 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/AaregConsumer.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/AaregConsumer.java @@ -1,16 +1,13 @@ package no.nav.testnav.levendearbeidsforholdansettelse.consumers; -import io.netty.channel.ChannelOption; -import io.netty.channel.epoll.EpollChannelOption; import lombok.extern.slf4j.Slf4j; import no.nav.testnav.levendearbeidsforholdansettelse.config.Consumers; import no.nav.testnav.levendearbeidsforholdansettelse.consumers.command.aareg.HentArbeidsforholdCommand; import no.nav.testnav.levendearbeidsforholdansettelse.consumers.command.aareg.OpprettArbeidsforholdCommand; +import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ArbeidsforholdResponseDTO; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; import no.nav.testnav.libs.securitycore.domain.ServerProperties; import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.ResponseEntity; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -44,7 +41,7 @@ public AaregConsumer( .create(ConnectionProvider.builder("AaregConsumer") .maxConnections(1) .pendingAcquireMaxCount(10000) - .pendingAcquireTimeout(Duration.ofSeconds(300)) + .pendingAcquireTimeout(Duration.ofSeconds(3000)) .build()) )) .build(); @@ -56,10 +53,10 @@ public Flux hentArbeidsforhold(String ident) { .flatMapMany(token -> new HentArbeidsforholdCommand(webClient, token.getTokenValue(), ident).call())); } - public Flux opprettArbeidsforhold(Arbeidsforhold requests) { + public Flux opprettArbeidsforhold(Arbeidsforhold requests) { return Flux.from(tokenExchange.exchange(serverProperties) - .flatMap(token -> new OpprettArbeidsforholdCommand(webClient, requests, token.getTokenValue()).call()) - .map(ResponseEntity::getStatusCode)); + .flatMap(token -> new OpprettArbeidsforholdCommand(webClient, + requests, token.getTokenValue()).call())); } } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java index 263800d4851..6bfb34c37fb 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.ExchangeStrategies; import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.List; @@ -39,12 +40,11 @@ public KodeverkServiceConsumer( objectMapper = new ObjectMapper(); } - public List hentKodeverk(String kodeverk) { + public Mono> hentKodeverk(String kodeverk) { return tokenExchange.exchange(serverProperties) .flatMap(token -> new KodeverkServiceCommand(webClient, token.getTokenValue(), kodeverk, objectMapper).call()) .map(Map::keySet) - .map(ArrayList::new) - .block(); + .map(ArrayList::new); } } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/PdlConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/PdlConsumer.java index 6c63af3560d..6f27d1a9398 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/PdlConsumer.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/PdlConsumer.java @@ -1,5 +1,6 @@ package no.nav.testnav.levendearbeidsforholdansettelse.consumers; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import lombok.val; import no.nav.testnav.levendearbeidsforholdansettelse.config.Consumers; @@ -11,8 +12,12 @@ import no.nav.testnav.libs.securitycore.domain.ServerProperties; import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.ExchangeStrategies; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; import reactor.netty.http.client.HttpClient; @@ -37,12 +42,21 @@ public class PdlConsumer { public PdlConsumer( TokenExchange tokenService, Consumers consumers, + ObjectMapper objectMapper, WebClient.Builder webClientBuilder) { serverProperties = consumers.getPdlProxy(); this.tokenService = tokenService; webClient = webClientBuilder .baseUrl(serverProperties.getUrl()) + .exchangeStrategies(ExchangeStrategies.builder() + .codecs(config -> { + config.defaultCodecs() + .jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON)); + config.defaultCodecs() + .jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON)); + }) + .build()) .clientConnector( new ReactorClientHttpConnector( HttpClient diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java index 1d5fb53956a..7ab9b5920f1 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java @@ -2,9 +2,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.levendearbeidsforholdansettelse.domain.NavHeaders; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; -import no.nav.testnav.libs.servletcore.headers.NavHeaders; import org.springframework.http.HttpHeaders; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -23,7 +23,7 @@ @RequiredArgsConstructor public class HentArbeidsforholdCommand implements Callable> { - private static final String miljoe = "q2"; + private static final String MILJOE = "q2"; private static final String NAV_PERSON_IDENT = "Nav-Personident"; private static final String CONSUMER = "Dolly"; @@ -45,7 +45,7 @@ public Flux call() { .queryParam("arbeidsforholdtype", "forenkletOppgjoersordning", "frilanserOppdragstakerHonorarPersonerMm", "maritimtArbeidsforhold", "ordinaertArbeidsforhold") - .build(miljoe)) + .build(MILJOE)) .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) .header(NAV_PERSON_IDENT, ident) .header(NavHeaders.NAV_CONSUMER_ID, CONSUMER) diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java index 76edef8cfb4..5e8c2414da2 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java @@ -2,20 +2,24 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ArbeidsforholdResponseDTO; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; 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.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 io.netty.handler.codec.http.HttpResponseStatus.CREATED; + @Slf4j @RequiredArgsConstructor -public class OpprettArbeidsforholdCommand implements Callable>> { +public class OpprettArbeidsforholdCommand implements Callable> { private final String navArbeidsforholdKilde = "Dolly-automatisk-ansettelse" ; private final String miljoe = "q2"; @@ -25,7 +29,7 @@ public class OpprettArbeidsforholdCommand implements Callable> call() { + public Mono call() { return webClient.post() .uri(builder -> builder.path("/{miljoe}/api/v1/arbeidsforhold") @@ -35,9 +39,17 @@ public Mono> call() { .header("Nav-Arbeidsforhold-Kildereferanse", navArbeidsforholdKilde) .bodyValue(requests) .retrieve() - .toBodilessEntity() + .bodyToMono(String.class) + .map(payload -> ArbeidsforholdResponseDTO.builder() + .statusCode(HttpStatusCode.valueOf(CREATED.code())) + .payload(payload) + .build()) .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) .filter(WebClientFilter::is5xxException)) - .doOnError(WebClientFilter::logErrorMessage); + .doOnError(WebClientFilter::logErrorMessage) + .onErrorResume(error -> Mono.just(ArbeidsforholdResponseDTO.builder() + .statusCode(WebClientFilter.getStatus(error)) + .feilmelding(WebClientFilter.getMessage(error)) + .build())); } } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java index c8e8aff85b2..2d52ec25141 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java @@ -1,7 +1,6 @@ package no.nav.testnav.levendearbeidsforholdansettelse.consumers.command.pdl; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.PdlPersonDTO; import no.nav.testnav.levendearbeidsforholdansettelse.domain.pdl.GraphqlVariables; import no.nav.testnav.levendearbeidsforholdansettelse.provider.PdlMiljoer; @@ -25,7 +24,6 @@ import static no.nav.testnav.levendearbeidsforholdansettelse.domain.pdl.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID; import static org.springframework.http.HttpHeaders.AUTHORIZATION; -@Slf4j @RequiredArgsConstructor public class SokPersonCommand implements Callable> { diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/LoggController.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/LoggController.java index 3e369388a0d..1d67f42ced9 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/LoggController.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/LoggController.java @@ -5,13 +5,15 @@ import no.nav.testnav.levendearbeidsforholdansettelse.entity.AnsettelseLogg; import no.nav.testnav.levendearbeidsforholdansettelse.service.LoggService; import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - -import java.util.List; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @RestController @RequestMapping("/api/v1/logg") @@ -22,21 +24,24 @@ public class LoggController { @GetMapping @Operation(description = "Henter logger i hht forespørsel") - public Page getAnsettelser(Pageable pageable) { + public Mono> getAnsettelser(@RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(defaultValue = "id") String... sort) { + var pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, sort)); return loggService.getAnsettelseLogg(pageable); } @GetMapping("/ident/{ident}") @Operation(description = "Henter logg i hht forespørsel") - public List getIdent(@PathVariable String ident) { + public Flux getIdent(@PathVariable String ident) { return loggService.getIdent(ident); } @GetMapping("/organisasjon/{orgnummer}") @Operation(description = "Henter logg i hht forespørsel") - public List getOrganisasjon(@PathVariable String orgnummer) { + public Flux getOrganisasjon(@PathVariable String orgnummer) { return loggService.getOrgnummer(orgnummer); } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/ParameterController.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/ParameterController.java index 1e0692cc0ab..eb92a65f120 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/ParameterController.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/controller/ParameterController.java @@ -5,8 +5,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ParameterDTO; +import no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameter; import no.nav.testnav.levendearbeidsforholdansettelse.service.ParameterService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -15,8 +15,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; - -import java.util.List; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @Slf4j @RestController @@ -24,7 +24,6 @@ @RequiredArgsConstructor public class ParameterController { - @Autowired private final ParameterService parameterService; /** @@ -33,7 +32,7 @@ public class ParameterController { */ @GetMapping @Operation(description = "Henter alle parametre for oppretting av arbeidsforhold") - public List hentAlleParametere() { + public Flux hentAlleParametere() { return parameterService.hentAlleParametere(); } @@ -46,8 +45,8 @@ public List hentAlleParametere() { @PutMapping("/{parameternavn}") @Operation(description = "Legg inn ny verdi på en parameter") @ResponseStatus(HttpStatus.OK) - public void oppdatereVerdier(@PathVariable("parameternavn") String parameternavn, @RequestBody String verdi){ + public Mono oppdatereVerdier(@PathVariable("parameternavn") String parameternavn, @RequestBody String verdi){ - parameterService.updateVerdi(parameternavn, verdi); + return parameterService.updateVerdi(parameternavn, verdi); } } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/NavHeaders.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/NavHeaders.java new file mode 100644 index 00000000000..f58ac8da888 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/NavHeaders.java @@ -0,0 +1,9 @@ +package no.nav.testnav.levendearbeidsforholdansettelse.domain; + +public class NavHeaders { + private NavHeaders() { + } + + public static final String NAV_CALL_ID = "Nav-Call-Id"; + public static final String NAV_CONSUMER_ID = "Nav-Consumer-Id"; +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/ArbeidsforholdResponseDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/ArbeidsforholdResponseDTO.java new file mode 100644 index 00000000000..5e582372bb5 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/ArbeidsforholdResponseDTO.java @@ -0,0 +1,18 @@ +package no.nav.testnav.levendearbeidsforholdansettelse.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.http.HttpStatusCode; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ArbeidsforholdResponseDTO { + + private HttpStatusCode statusCode; + private String payload; + private String feilmelding; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/PdlPersonDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/PdlPersonDTO.java index f07c3fddfd5..a6207a63704 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/PdlPersonDTO.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/domain/dto/PdlPersonDTO.java @@ -1,5 +1,6 @@ package no.nav.testnav.levendearbeidsforholdansettelse.domain.dto; +import com.fasterxml.jackson.databind.JsonNode; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -20,6 +21,8 @@ @AllArgsConstructor public class PdlPersonDTO { + private JsonNode errors; + private Data data; public enum Gruppe {AKTORID, FOLKEREGISTERIDENT, NPID} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java index a7bb270114e..363a592c87b 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java @@ -1,63 +1,61 @@ package no.nav.testnav.levendearbeidsforholdansettelse.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.Table; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.domain.Persistable; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; -import java.math.BigDecimal; import java.time.LocalDate; -import java.time.OffsetDateTime; +import java.time.LocalDateTime; @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Entity @Table(name = "ansettelse_logg") -public class AnsettelseLogg { +public class AnsettelseLogg implements Persistable { + + @Transient + private boolean isNew; + @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") - @SequenceGenerator(name = "seq", sequenceName = "ansettelse_logg_id_seq", allocationSize = 1) - @Column(name = "id", nullable = false) + @NotNull + @Column("id") private Integer id; @Size(max = 255) @NotNull - @Column(name = "organisasjonsnummer", nullable = false) + @Column("organisasjonsnummer") private String organisasjonsnummer; @Size(max = 255) @NotNull - @Column(name = "folkeregisterident", nullable = false) + @Column("folkeregisterident") private String folkeregisterident; @NotNull - @Column(name = "timestamp", nullable = false) - private OffsetDateTime timestamp; + @Column("timestamp") + private LocalDateTime timestamp; @NotNull - @Column(name = "ansattfra", nullable = false) + @Column("ansattfra") private LocalDate ansattfra; @Size(max = 255) - @Column(name = "arbeidsforhold_type") + @Column("arbeidsforhold_type") private String arbeidsforholdType; - @Column(name = "stillingsprosent") + @Column("stillingsprosent") private Integer stillingsprosent; @Override @@ -73,4 +71,10 @@ public boolean equals(Object o) { public int hashCode() { return new HashCodeBuilder(17, 37).append(getId()).append(getOrganisasjonsnummer()).append(getFolkeregisterident()).append(getTimestamp()).append(getAnsattfra()).append(getArbeidsforholdType()).append(getStillingsprosent()).toHashCode(); } + + @Override + @JsonIgnore + public boolean isNew() { + return isNew; + } } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/JobbParameter.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/JobbParameter.java index f83a7253fc2..ae87f7e5b36 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/JobbParameter.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/entity/JobbParameter.java @@ -1,35 +1,39 @@ package no.nav.testnav.levendearbeidsforholdansettelse.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.domain.Persistable; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; @Data -@Entity @Table(name = "jobb_parameter") -public class JobbParameter { +public class JobbParameter implements Persistable { + + @Transient + private boolean isNew; @Id @Size(max = 255) - @Column(name = "navn", nullable = false) + @Column("navn") private String navn; @Size(max = 255) @NotNull - @Column(name = "tekst", nullable = false) + @Column("tekst") private String tekst; @Size(max = 255) - @Column(name = "verdi") + @Column("verdi") private String verdi; - @Column(name = "verdier") + @Column("verdier") private String verdier; @Override @@ -45,4 +49,15 @@ public boolean equals(Object o) { public int hashCode() { return new HashCodeBuilder(17, 37).append(getNavn()).append(getTekst()).append(getVerdi()).append(getVerdier()).toHashCode(); } + + @Override + public String getId() { + return navn; + } + + @Override + @JsonIgnore + public boolean isNew() { + return isNew; + } } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java index b1407856edb..4a2043b2492 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java @@ -1,12 +1,14 @@ package no.nav.testnav.levendearbeidsforholdansettelse.repository; import no.nav.testnav.levendearbeidsforholdansettelse.entity.AnsettelseLogg; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; -import java.util.List; +@Repository +public interface AnsettelseLoggRepository extends R2dbcRepository { -public interface AnsettelseLoggRepository extends CrudRepository { + Flux findByFolkeregisterident(String ident); + Flux findByOrganisasjonsnummer(String orgnummer); - List findByFolkeregisterident(String ident); - List findByOrganisasjonsnummer(String orgnummer); } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/LoggRepository.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/LoggRepository.java index 0159dc3608b..0a404194fef 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/LoggRepository.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/LoggRepository.java @@ -1,7 +1,16 @@ package no.nav.testnav.levendearbeidsforholdansettelse.repository; import no.nav.testnav.levendearbeidsforholdansettelse.entity.AnsettelseLogg; -import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.domain.Pageable; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Repository +public interface LoggRepository extends R2dbcRepository { + + Flux findAllBy(Pageable pageable); + Mono countAllBy(); -public interface LoggRepository extends PagingAndSortingRepository { } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/ParameterRepository.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/ParameterRepository.java index a4e5d29920e..ee237eff1e9 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/ParameterRepository.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/repository/ParameterRepository.java @@ -1,11 +1,9 @@ package no.nav.testnav.levendearbeidsforholdansettelse.repository; import no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameter; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; -import java.util.List; - -public interface ParameterRepository extends CrudRepository { - - List findAll(); +@Repository +public interface ParameterRepository extends R2dbcRepository { } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java index f5c59ad428f..abee69b3366 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java @@ -6,9 +6,10 @@ import no.nav.testnav.levendearbeidsforholdansettelse.entity.AnsettelseLogg; import no.nav.testnav.levendearbeidsforholdansettelse.repository.AnsettelseLoggRepository; import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; import java.time.LocalDate; -import java.time.OffsetDateTime; +import java.time.LocalDateTime; import java.util.Map; import static no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ARBEIDSFORHOLD_TYPE; @@ -26,15 +27,17 @@ public class AnsettelseLoggService { /** * Funksjonen som lagrer ansettelsen i db + * * @param kanAnsette inneholder ident og orgnummer * @param parametere Stillingsprosent og arbeidsavtalarbeidsforholdType til personen. */ - public AnsettelseLogg lagreAnsettelse(KanAnsettesDTO kanAnsette, Map parametere){ + public Mono lagreAnsettelse(KanAnsettesDTO kanAnsette, Map parametere) { return ansettelseLoggRepository.save(AnsettelseLogg.builder() + .isNew(true) .folkeregisterident(kanAnsette.getIdent()) .organisasjonsnummer(kanAnsette.getOrgnummer()) - .timestamp(OffsetDateTime.now()) + .timestamp(LocalDateTime.now()) .arbeidsforholdType(parametere.get(ARBEIDSFORHOLD_TYPE.value)) .stillingsprosent(Integer.parseInt(parametere.get(STILLINGSPROSENT.value))) .ansattfra(LocalDate.now()) diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseService.java index fc7319c60f7..9c522152ff9 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/AnsettelseService.java @@ -5,6 +5,7 @@ import no.nav.testnav.levendearbeidsforholdansettelse.consumers.TenorConsumer; import no.nav.testnav.levendearbeidsforholdansettelse.domain.DatoIntervall; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ArbeidsforholdDTO; +import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ArbeidsforholdResponseDTO; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.KanAnsettesDTO; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.OrganisasjonResponseDTO; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.PdlPersonDTO; @@ -14,15 +15,15 @@ import no.nav.testnav.levendearbeidsforholdansettelse.utility.SannsynlighetVelger; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsavtale; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; -import org.springframework.http.HttpStatusCode; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; +import java.security.SecureRandom; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; @@ -30,6 +31,7 @@ import static no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ANTALL_PERSONER; import static no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ARBEIDSFORHOLD_TYPE; import static no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameterNavn.STILLINGSPROSENT; +import static org.apache.commons.lang3.BooleanUtils.isTrue; import static org.apache.commons.lang3.StringUtils.isNumeric; @Slf4j @@ -37,6 +39,9 @@ @RequiredArgsConstructor public class AnsettelseService { + private static final Random RANDOM = new SecureRandom(); + private static final Integer ANTALL_RETRIES = 3; + private final PdlService pdlService; private final TenorConsumer tenorConsumer; private final ArbeidsforholdService arbeidsforholdService; @@ -47,42 +52,26 @@ public class AnsettelseService { @Async public void runAnsettelseService() { - Thread thread = new Thread(this::ansettelseService); - thread.start(); - try { - thread.join(3_500_000); //Timeout etter 3000 sekunder - if (thread.isAlive()) { - thread.interrupt(); - log.info("Timeout occurred"); - } - } catch (InterruptedException e) { - log.info("Timet ut"); - } - } - - @Transactional - public void ansettelseService() { - var startTime = System.currentTimeMillis(); //Henter parametere fra db - var parametere = parameterService.hentParametere(); - log.info("Startet oppretting av {} personer i {} organisasjoner", parametere.get("antallPersoner"), - parametere.get("antallOrganisasjoner")); + var parametere = parameterService.hentParametere() + .doOnNext(param -> + log.info("Startet oppretting av {} personer i {} organisasjoner", + param.get("antallPersoner"), + param.get("antallOrganisasjoner"))); //Henter yrkeskoder for å gi tilfeldige yrker var yrkeskoder = kodeverkService.hentKodeverkValues(KodeverkNavn.YRKER.value); - if (yrkeskoder.isEmpty()) { - return; - } //Initialiserer liste over alderspenn og liste med tidligste og seneste gyldig dato for ansttelse var datoIntervaller = SannsynlighetVelger.getDatointervaller(); //Kjører ansettelse per org - Flux.range(0, (int) getParameterValue(parametere, ANTALL_ORGANISASJONER)) - .flatMap(count -> tenorConsumer.hentOrganisasjon()) - .flatMap(organisasjon -> sjekkOgSendinnArbeidsforhold(organisasjon, parametere, yrkeskoder, datoIntervaller)) + Flux.zip(parametere, yrkeskoder) + .flatMap(tuple -> Flux.range(0, (int) getParameterValue(tuple.getT1(), ANTALL_ORGANISASJONER)) + .flatMap(count -> tenorConsumer.hentOrganisasjon()) + .flatMap(organisasjon -> sjekkOgSendinnArbeidsforhold(organisasjon, tuple.getT1(), tuple.getT2(), datoIntervaller))) .collectList() .subscribe(status -> log.info("Oppretting ferdig, antall ansettelser {}, medgått tid {} sekunder", status.size(), (System.currentTimeMillis() - startTime) / 1000)); @@ -91,22 +80,45 @@ public void ansettelseService() { private Flux sjekkOgSendinnArbeidsforhold(OrganisasjonResponseDTO organisasjon, Map parametere, List yrkeskoder, List datointervaller) { - return Flux.fromIterable(getFordeling(parametere).entrySet()) + return Flux.fromIterable(getFordeling(parametere).entrySet()) + .limitRate(1) .flatMap(intervall -> Flux.range(0, intervall.getValue()) - .flatMap(index -> getPersonSomKanAnsettes((int) getParameterValue(parametere, STILLINGSPROSENT), - datointervaller.get(intervall.getKey()), organisasjon) - .flatMap(kanAnsettes -> ansettPerson(kanAnsettes, hentTilfeldigYrkeskode(yrkeskoder), parametere) - .doOnNext(status -> log.info("Opprettet arbeidsforhold orgnummer {}, ident {}, status {}", - kanAnsettes.getOrgnummer(), kanAnsettes.getIdent(), status)) - .map(status -> - ansettelseLoggService.lagreAnsettelse(kanAnsettes, parametere))))); + .flatMap(index -> hentOgAnsett(organisasjon, parametere, + hentTilfeldigYrkeskode(yrkeskoder), + datointervaller.get(intervall.getKey()), new AtomicInteger(ANTALL_RETRIES)))); + } + + private Flux hentOgAnsett(OrganisasjonResponseDTO organisasjon, + Map parametere, + String yrkeskode, DatoIntervall datointervall, AtomicInteger retries) { + + if (retries.get() == 0) { + return Flux.empty(); + } + + return getPersonSomKanAnsettes((int) getParameterValue(parametere, STILLINGSPROSENT), + datointervall, organisasjon) + .flatMap(kanAnsettes -> ansettPerson(kanAnsettes, yrkeskode, parametere) + .flatMap(response -> { + if (response.getStatusCode().is2xxSuccessful()) { + log.info("Opprettet arbeidsforhold orgnummer {}, ident {}, status {}", + kanAnsettes.getOrgnummer(), kanAnsettes.getIdent(), response.getStatusCode()); + return ansettelseLoggService.lagreAnsettelse(kanAnsettes, parametere); + } else { + log.error("Oppretting mot AAREG feilet, orgnummer {}, ident {} med feilmelding {} ", + kanAnsettes.getOrgnummer(), kanAnsettes.getIdent(), response.getFeilmelding()); + return hentOgAnsett(organisasjon, parametere, + yrkeskode, + datointervall, new AtomicInteger(retries.decrementAndGet())); + } + })); } private Flux getPersonSomKanAnsettes(Integer stillingsprosent, DatoIntervall intervall, OrganisasjonResponseDTO organisasjon) { return getArbeidsforhold(intervall, organisasjon.getPostnummer()) - .map(arbeidsforhold1 -> Flux.fromIterable(arbeidsforhold1.getArbeidsforhold()) + .flatMap(arbeidsforhold1 -> Flux.fromIterable(arbeidsforhold1.getArbeidsforhold()) .map(Arbeidsforhold::getArbeidsavtaler) .flatMap(Flux::fromIterable) .filter(arbeidsavtale -> nonNull(arbeidsavtale.getBruksperiode()) && @@ -116,7 +128,7 @@ private Flux getPersonSomKanAnsettes(Integer stillingsprosent, D .reduce(0, (a, b) -> (int) (a + b)) .map(sum -> sum + stillingsprosent <= 100) .map(done -> { - if (done) { + if (isTrue(done)) { return Flux.just(KanAnsettesDTO.builder() .ident(arbeidsforhold1.getIdent()) .orgnummer(organisasjon.getOrgnummer()) @@ -127,13 +139,17 @@ private Flux getPersonSomKanAnsettes(Integer stillingsprosent, D return getPersonSomKanAnsettes(stillingsprosent, intervall, organisasjon); } })) - .flatMap(Flux::from) .flatMap(Flux::from); } private Flux getArbeidsforhold(DatoIntervall datoIntervall, String postnummer) { return pdlService.getPerson(datoIntervall, postnummer) + .doOnNext(person -> log.info("Hentet person fra PDL med ident {}", + person.getFolkeregisteridentifikator().stream() + .filter(PdlPersonDTO.Person.Folkeregisteridentifikator::isIBRUK) + .map(PdlPersonDTO.Person.Folkeregisteridentifikator::getIdentifikasjonsnummer) + .findFirst().orElse(null))) .flatMap(person -> Flux.fromIterable(person.getFolkeregisteridentifikator()) .filter(PdlPersonDTO.Person.Folkeregisteridentifikator::isIBRUK) .map(PdlPersonDTO.Person.Folkeregisteridentifikator::getIdentifikasjonsnummer)) @@ -145,8 +161,8 @@ private Flux getArbeidsforhold(DatoIntervall datoIntervall, S .build())); } - private Flux ansettPerson(KanAnsettesDTO arbeidsforhold, String yrke, - Map parametere) { + private Flux ansettPerson(KanAnsettesDTO arbeidsforhold, String yrke, + Map parametere) { return arbeidsforholdService.opprettArbeidsforhold(arbeidsforhold, yrke, (String) getParameterValue(parametere, ARBEIDSFORHOLD_TYPE), @@ -160,13 +176,9 @@ private static int getAntallAnsettelserIHverOrg(Map parametere) (int) getParameterValue(parametere, ANTALL_ORGANISASJONER); } - private int tilfeldigTall(int max) { - Random random = new Random(); - return random.nextInt(max); - } - private String hentTilfeldigYrkeskode(List yrkeskoder) { - return yrkeskoder.get(tilfeldigTall(yrkeskoder.size())); + + return yrkeskoder.get(RANDOM.nextInt(yrkeskoder.size())); } private static Object getParameterValue(Map parametere, JobbParameterNavn parameterNavn) { diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java index 66b479053cc..1c843b4d62b 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.testnav.levendearbeidsforholdansettelse.consumers.AaregConsumer; +import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ArbeidsforholdResponseDTO; import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.KanAnsettesDTO; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Ansettelsesperiode; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; @@ -10,13 +11,11 @@ import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Organisasjon; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Periode; import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Person; -import org.springframework.http.HttpStatusCode; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.math.BigDecimal; import java.math.RoundingMode; -import java.time.Duration; import java.time.LocalDate; import java.util.List; @@ -25,10 +24,10 @@ @RequiredArgsConstructor public class ArbeidsforholdService { - private static final String arbeidstakerType = "Person"; - private static final String arbeidsgiverType = "Organisasjon"; - private static final String arbeidstidsordning = "ikkeSkift"; - private static final String ansettelsesform = "fast"; + private static final String ARBEIDSTAKER_TYPE = "Person"; + private static final String ARBEIDSGIVER_TYPE = "Organisasjon"; + private static final String ARBEIDSTIDSORDNING = "ikkeSkift"; + private static final String ANSETTELSESFORM = "fast"; private static final double TIMER_HUNDRE_PROSENT = 37.5; private static final int HUNDRE_PROSENT = 100; @@ -51,11 +50,11 @@ public Flux getArbeidsforhold(String ident) { * @param stillingsprosent Stillinsprosenten arbeidsforholdet skal ha * @return HttpStatusCode basert på resultatet av spørringen */ - public Flux opprettArbeidsforhold(KanAnsettesDTO kanAnsettes, String yrke, - String arbeidsforholdstype, Integer stillingsprosent) { + public Flux opprettArbeidsforhold(KanAnsettesDTO kanAnsettes, String yrke, + String arbeidsforholdstype, Integer stillingsprosent) { - return aaregConsumer.opprettArbeidsforhold(lagArbeidsforhold(kanAnsettes, yrke, arbeidsforholdstype, stillingsprosent)) - .delayElements(Duration.ofSeconds(1)); + return aaregConsumer.opprettArbeidsforhold(lagArbeidsforhold(kanAnsettes, + yrke, arbeidsforholdstype, stillingsprosent)); } /** @@ -75,11 +74,11 @@ private Arbeidsforhold lagArbeidsforhold(KanAnsettesDTO kanAnsettes, String yrke .arbeidsforholdId(Integer.toString(kanAnsettes.getAntallEksisterendeArbeidsforhold() + 1)) .arbeidstaker(Person.builder() .offentligIdent(kanAnsettes.getIdent()) - .type(arbeidstakerType) + .type(ARBEIDSTAKER_TYPE) .build()) .arbeidsgiver(Organisasjon.builder() .organisasjonsnummer(kanAnsettes.getOrgnummer()) - .type(arbeidsgiverType) + .type(ARBEIDSGIVER_TYPE) .build()) .type(arbeidsforholdType) .ansettelsesperiode(Ansettelsesperiode.builder() @@ -89,10 +88,10 @@ private Arbeidsforhold lagArbeidsforhold(KanAnsettesDTO kanAnsettes, String yrke .build()) .arbeidsavtaler(List.of(OrdinaerArbeidsavtale.builder() .antallTimerPrUke(antallTimerPrUke) - .arbeidstidsordning(arbeidstidsordning) + .arbeidstidsordning(ARBEIDSTIDSORDNING) .stillingsprosent(stillingsprosent) .yrke(yrke) - .ansettelsesform(ansettelsesform) + .ansettelsesform(ANSETTELSESFORM) .sistStillingsendring(LocalDate.now()) .build())) .build(); diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/KodeverkService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/KodeverkService.java index 82344771753..204361d88c0 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/KodeverkService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/KodeverkService.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import no.nav.testnav.levendearbeidsforholdansettelse.consumers.KodeverkServiceConsumer; import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; import java.util.List; @@ -21,8 +22,8 @@ public class KodeverkService { * @param kodeverk String som er navnet på kodeverket. * @return En liste av String som er kodene. */ - public List hentKodeverkValues(String kodeverk){ + public Mono> hentKodeverkValues(String kodeverk){ + return kodeverkServiceConsumer.hentKodeverk(kodeverk); } - } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/LoggService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/LoggService.java index 1e6a225f1f4..720c7b6fc97 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/LoggService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/LoggService.java @@ -5,11 +5,11 @@ import no.nav.testnav.levendearbeidsforholdansettelse.repository.AnsettelseLoggRepository; import no.nav.testnav.levendearbeidsforholdansettelse.repository.LoggRepository; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @Service @RequiredArgsConstructor @@ -18,20 +18,20 @@ public class LoggService { private final LoggRepository loggRepository; private final AnsettelseLoggRepository ansettelseLoggRepository; - @Transactional(readOnly = true) - public Page getAnsettelseLogg(Pageable pageable) { + public Mono> getAnsettelseLogg(Pageable pageable) { - return loggRepository.findAll(pageable); + return loggRepository.findAllBy(pageable) + .collectList() + .zipWith(loggRepository.countAllBy()) + .map(tuple -> new PageImpl<>(tuple.getT1(), pageable, tuple.getT2())); } - @Transactional(readOnly = true) - public List getIdent(String ident) { + public Flux getIdent(String ident) { return ansettelseLoggRepository.findByFolkeregisterident(ident); } - @Transactional(readOnly = true) - public List getOrgnummer(String orgnummer) { + public Flux getOrgnummer(String orgnummer) { return ansettelseLoggRepository.findByOrganisasjonsnummer(orgnummer); } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ParameterService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ParameterService.java index 2dee53e4cfd..50118cc9eb7 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ParameterService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/ParameterService.java @@ -5,13 +5,11 @@ import no.nav.testnav.levendearbeidsforholdansettelse.domain.dto.ParameterDTO; import no.nav.testnav.levendearbeidsforholdansettelse.entity.JobbParameter; import no.nav.testnav.levendearbeidsforholdansettelse.repository.ParameterRepository; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.server.ResponseStatusException; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -30,16 +28,15 @@ public class ParameterService { * * @return Returnerer en liste av JobbParameterObjektene til alle parameterne */ - public List hentAlleParametere() { + public Flux hentAlleParametere() { - return parameterRepository.findAll().stream() + return parameterRepository.findAll() .map(parameter -> ParameterDTO.builder() .navn(parameter.getNavn()) .tekst(parameter.getTekst()) .verdi(parameter.getVerdi()) .verdier(Arrays.asList(parameter.getVerdier().split(","))) - .build()) - .toList(); + .build()); } /** @@ -47,9 +44,9 @@ public List hentAlleParametere() { * * @return ett map av JobbParameter navnet og verdier */ - public Map hentParametere() { + public Mono> hentParametere() { - return parameterRepository.findAll().stream() + return parameterRepository.findAll() .collect(Collectors.toMap(JobbParameter::getNavn, JobbParameter::getVerdi)); } @@ -60,14 +57,14 @@ public Map hentParametere() { * @param verdi ny verdi for parameter */ - @Transactional - public void updateVerdi(String parameternavn, String verdi) { + public Mono updateVerdi(String parameternavn, String verdi) { - parameterRepository.findById(parameternavn) - .ifPresentOrElse(parameter -> parameter.setVerdi(verdi), - () -> { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, - "Parameter med navn %s ble ikke funnet".formatted(parameternavn)); - }); + return parameterRepository.findById(parameternavn) + .map(parameter -> { + parameter.setVerdi(verdi); + return parameter; + } + ) + .flatMap(parameterRepository::save); } } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/PdlService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/PdlService.java index 5c671b8c5b4..01c94ece9f0 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/PdlService.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/service/PdlService.java @@ -23,6 +23,7 @@ public class PdlService { private static final Random RANDOM = new SecureRandom(); + private static final String CONTAINS = "contains"; private final PdlConsumer pdlConsumer; @@ -38,6 +39,7 @@ public Flux getPerson(DatoIntervall datoIntervall, String p return pdlConsumer.getSokPerson(lagSokPersonPaging(1), lagSokPersonCriteria(datoIntervall, postnummer), PdlMiljoer.Q2) + .filter(data -> nonNull(data.getData())) .map(PdlPersonDTO::getData) .filter(data -> nonNull(data.getSokPerson())) .map(PdlPersonDTO.Data::getSokPerson) @@ -71,17 +73,17 @@ private GraphqlVariables.Criteria lagSokPersonCriteria(DatoIntervall intervall, GraphqlVariables.Filter testnorge = GraphqlVariables.Filter.builder() .fieldName("tags") - .searchRule(Map.of("contains", "TESTNORGE")) + .searchRule(Map.of(CONTAINS, "TESTNORGE")) .build(); GraphqlVariables.Filter dolly = GraphqlVariables.Filter.builder() .fieldName("tags") - .searchRule(Map.of("contains", "DOLLY")) + .searchRule(Map.of(CONTAINS, "DOLLY")) .build(); GraphqlVariables.Filter arenasynt = GraphqlVariables.Filter.builder() .fieldName("tags") - .searchRule(Map.of("contains", "ARENASYNT")) + .searchRule(Map.of(CONTAINS, "ARENASYNT")) .build(); var or = Map.of("or", List.of(filterBostedPostnr, filterOppholdPostnr)); diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/utility/PageableHandlerMethodArgumentResolver.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/utility/PageableHandlerMethodArgumentResolver.java new file mode 100644 index 00000000000..3e2f14ef144 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/testnav/levendearbeidsforholdansettelse/utility/PageableHandlerMethodArgumentResolver.java @@ -0,0 +1,63 @@ +package no.nav.testnav.levendearbeidsforholdansettelse.utility; + +import org.springframework.core.MethodParameter; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.web.reactive.BindingContext; +import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.List; + +import static java.util.Objects.nonNull; + +public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { + + private static final String DEFAULT_PAGE = "0"; + private static final String DEFAULT_SIZE = "10"; + private static final Integer MAX_SIZE = 50; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return Pageable.class.equals(parameter.getParameterType()); + } + + @Override + public Mono resolveArgument(MethodParameter methodParameter, + BindingContext bindingContext, + ServerWebExchange serverWebExchange) { + + var pageValues = serverWebExchange.getRequest() + .getQueryParams() + .getOrDefault("page", List.of(DEFAULT_PAGE)); + var sizeValues = serverWebExchange.getRequest() + .getQueryParams() + .getOrDefault("size", List.of(DEFAULT_SIZE)); + + var page = pageValues.getFirst(); + + var sortParam = serverWebExchange.getRequest() + .getQueryParams().getFirst("sort"); + + var sort = Sort.unsorted(); + + if (nonNull(sortParam)) { + var parts = sortParam.split(","); + if (parts.length == 2) { + var property = parts[0]; + var direction = Sort.Direction.fromString(parts[1]); + sort = Sort.by(direction, property); + } + } + + return Mono.just( + PageRequest.of( + Integer.parseInt(page), + Math.min(Integer.parseInt(sizeValues.getFirst()), + MAX_SIZE), sort + ) + ); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml index 44846a38ac7..8e05042d920 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml @@ -1,27 +1,33 @@ spring: - h2: - console: - enabled: true - path: /h2 - datasource: - url: jdbc:h2:mem:testdb - username: sa + flyway: + # InMemmory database + url: jdbc:postgresql://localhost:5432/testnav-levende-arbeidsforhold + user: ${NAV_USERNAME} password: - driverClassName: org.h2.Driver - sql: - init: - mode: always - data-locations: classpath:/db/dev/h2-default-config.sql + r2dbc: + url: r2dbc:postgresql://localhost:5432/testnav-levende-arbeidsforhold + username: ${NAV_USERNAME} + password: +# sql: +# init: +# mode: always +# data-locations: classpath:/db/dev/h2-default-config.sql + +# main: +# allow-bean-definition-overriding: true +# +#config: +# r2dbc: +# driver: h2 +# protocol: mem +# port: 5432 +# database: testdb +# username: sa +# password: consumers: testnav-kodeverk-service: url: https://testnav-kodeverk-service.intern.dev.nav.no - name: testnav-kodeverk-service - cluster: dev-gcp - namespace: dolly testnav-tenor-search-service: - url: https://testnav-tenor-search-service.intern.dev.nav.no - name: testnav-tenor-search-service - cluster: dev-gcp - namespace: dolly \ No newline at end of file + url: https://testnav-tenor-search-service.intern.dev.nav.no \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml index 38ddcad04da..67030d4ac12 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml @@ -1,12 +1,14 @@ spring: - datasource: - url: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_JDBC_URL} - driverClassName: org.postgresql.Driver - hikari: - maximum-pool-size: 3 - minimum-idle: 0 - jpa: - database: POSTGRESQL + r2dbc: + url: r2dbc:postgresql://${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_HOST}:${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_PORT}/${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_DATABASE} + username: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_USERNAME} + password: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_PASSWORD} properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file + sslCert: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_SSLCERT} + sslKey: /tmp/pk8.pem # See Dockerfile and 99-dolly-convert-to-pk8.sh. + sslMode: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_SSLMODE} + sslRootCert: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_SSLROOTCERT} + flyway: + url: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_JDBC_URL} + user: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_USERNAME} + password: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_TESTNAV_LEVENDE_ARBEIDSFORHOLD_PASSWORD} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml index b1858ad73ad..f04dd806222 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml @@ -35,8 +35,9 @@ management: path-mapping: prometheus: metrics endpoint: - prometheus.enabled: true + health.show-details: always heapdump.enabled: true + prometheus.enabled: true prometheus: metrics: export: diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/dev/h2-default-config.sql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/dev/h2-default-config.sql index 1f3f24c6599..8dcdec671ff 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/dev/h2-default-config.sql +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/dev/h2-default-config.sql @@ -1,8 +1,9 @@ -- Default verdier for kjøring med H2 -insert into jobb_parameter values('stillingsprosent','Stillingsprosent','80','20,30,40,50,60,70,80,90,100'); -insert into jobb_parameter values('intervall','Intervall for neste kjøring (timer)','1','1,5,12,24,168'); -insert into jobb_parameter values('antallOrganisasjoner','Antall Organisasjoner','1','1,5,10,15,20,25,30,35,40,45,50'); -insert into jobb_parameter values('antallPersoner','Antall Personer','1','1,10,15,20,25,30,35,40,45,50,1001'); -insert into jobb_parameter values('arbeidsforholdType','Arbeidsforhold Type','ordinaertArbeidsforhold','forenkletOppgjoersordning,frilanserOppdragstakerHonorarPersonerMm,maritimtArbeidsforhold,ordinaertArbeidsforhold'); +insert into jobb_parameter(navn, tekst, verdi, verdier) values('stillingsprosent','Stillingsprosent','80','20,30,40,50,60,70,80,90,100'); +insert into jobb_parameter(navn, tekst, verdi, verdier) values('intervall','Intervall for neste kjøring (timer)','1','1,5,12,24,168'); +insert into jobb_parameter(navn, tekst, verdi, verdier) values('antallOrganisasjoner','Antall Organisasjoner','1','1,5,10,15,20,25,30,35,40,45,50'); +insert into jobb_parameter(navn, tekst, verdi, verdier) values('antallPersoner','Antall Personer','1','1,10,15,20,25,30,35,40,45,50,1001'); +insert into jobb_parameter(navn, tekst, verdi, verdier) values('arbeidsforholdType','Arbeidsforhold Type','ordinaertArbeidsforhold','forenkletOppgjoersordning,frilanserOppdragstakerHonorarPersonerMm,maritimtArbeidsforhold,ordinaertArbeidsforhold'); + commit; \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.2.0__ModifyPrimaryKey.sql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.2.0__ModifyPrimaryKey.sql new file mode 100644 index 00000000000..9db5c6b644f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.2.0__ModifyPrimaryKey.sql @@ -0,0 +1,6 @@ +----------------------------------- +-- M O D I F Y I N D E C I E S -- +----------------------------------- + +ALTER TABLE ansettelse_logg +ALTER COLUMN id SET DEFAULT NEXTVAL('ansettelse_logg_id_seq'); diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml index 5f39b7c7b9b..7feaa817ab0 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml @@ -2,19 +2,10 @@ - - - true - - 10280 - 20 - ^sun\.reflect\..*\.invoke - ^net\.sf\.cglib\.proxy\.MethodProxy\.invoke - java\.util\.concurrent\..* - org\.apache\.catalina\..* - org\.apache\.coyote\..* - org\.apache\.tomcat\..* - + + -1 + true + - diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql index d0209854938..db34cec7313 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql @@ -432,6 +432,11 @@ type Navn { originaltNavn: OriginaltNavn } +type Navspersonidentifikator { + identifikasjonsnummer: String! + metadata: Metadata! +} + type Opphold { folkeregistermetadata: Folkeregistermetadata! metadata: Metadata! @@ -479,6 +484,7 @@ type Person { kontaktadresse(historikk: Boolean = false): [Kontaktadresse!]! kontaktinformasjonForDoedsbo(historikk: Boolean = false): [KontaktinformasjonForDoedsbo!]! navn(historikk: Boolean = false): [Navn!]! + navspersonidentifikator(historikk: Boolean = false): [Navspersonidentifikator!]! opphold(historikk: Boolean = false): [Opphold!]! oppholdsadresse(historikk: Boolean = false): [Oppholdsadresse!]! rettsligHandleevne(historikk: Boolean = false): [RettsligHandleevne!]! @@ -893,7 +899,7 @@ input SearchRule { " Begrenser treff til kun de hvor felt har input verdi" equals: String " Sjekker om feltet finnes / at det ikke har en null verdi." - exists: String + exists: Boolean """ Søk fra og med (se fromExcluding for bare fra men ikke med) @@ -915,7 +921,7 @@ input SearchRule { " Filtrerer bort treff hvor felt inneholder input verdi" notEquals: String " Søk som gir tilfeldig poengsum til hvert treff (kun ment til generering av testdata)" - random: String + random: Float " Regex søk for spesielle situasjoner (Dette er en treg opprasjon og bør ikke brukes)" regex: String " Gir treff når opgitt feltstarter med opgitt verdi." diff --git a/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java b/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java index 569b084d2ac..f0251a8e160 100644 --- a/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java +++ b/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/testnav/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java @@ -1,19 +1,55 @@ package no.nav.testnav.levendearbeidsforholdansettelse; +import io.netty.handler.ssl.SslContextBuilder; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; +import org.springframework.test.context.ActiveProfiles; + +import java.io.File; +import java.io.FileInputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.fail; @SpringBootTest +@ActiveProfiles("test") class LevendeArbeidsforholdAnsettelseApplicationTests { @MockBean + @SuppressWarnings("unused") public ReactiveJwtDecoder jwtDecoder; + @Autowired + private R2dbcEntityTemplate template; + @Test - @SuppressWarnings("java:S2699") void load_app_context() { + assertThat(template) + .isNotNull(); + } + + @Disabled("Useful for checking the format of a SSL key file manually.") + @Test + @SuppressWarnings("java:S2699") + void attemptToLoadSslKeyFile() + throws Exception { + var sslKey = "key.pk8"; + System.err.println("SSL Key File: " + sslKey); + var file = new File(sslKey); + System.out.println("File " + file.getAbsolutePath() + (file.exists() ? " exists" : " not found")); + if (!file.exists()) { + fail(); + } else { + SslContextBuilder + .forClient() + .keyManager(null, new FileInputStream(file), null) + .build(); + } } } diff --git a/apps/levende-arbeidsforhold-ansettelse/src/test/resources/application-test.yml b/apps/levende-arbeidsforhold-ansettelse/src/test/resources/application-test.yml new file mode 100644 index 00000000000..00672563fc5 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/test/resources/application-test.yml @@ -0,0 +1,5 @@ +spring: + r2dbc: + url: r2dbc:h2:mem:///~/db/testdb + username: sa + password: \ No newline at end of file diff --git a/docs/compose.yaml b/docs/compose.yaml index c957309a956..02a8dafd3c2 100644 --- a/docs/compose.yaml +++ b/docs/compose.yaml @@ -27,4 +27,14 @@ services: - POSTGRES_HOST_AUTH_METHOD=trust ports: - "5434:5432" + restart: always + + postgres-levende-arbeidforhold: + container_name: postgres-levende-arbeidforhold-test + image: postgres:latest + environment: + - POSTGRES_DB=postgres-levende-arbeidforhold-test + - POSTGRES_HOST_AUTH_METHOD=trust + ports: + - "5435:5432" restart: always \ No newline at end of file diff --git a/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/LocalVaultConfig.java b/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/LocalVaultConfig.java index afcd86c9291..ba9ff220d64 100644 --- a/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/LocalVaultConfig.java +++ b/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/LocalVaultConfig.java @@ -3,10 +3,8 @@ import no.nav.testnav.libs.vault.AbstractLocalVaultConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.vault.annotation.VaultPropertySource; @Configuration @Profile("local") -@VaultPropertySource(value = "azuread/prod/creds/team-dolly-lokal-app", ignoreSecretNotFound = false) public class LocalVaultConfig extends AbstractLocalVaultConfiguration { } \ No newline at end of file diff --git a/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/SecurityConfig.java b/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/SecurityConfig.java index 616aebdc994..80bde93dfc0 100644 --- a/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/SecurityConfig.java +++ b/examples/reactive-rest-example/src/main/java/no/nav/testnav/examples/reactiverestexample/config/SecurityConfig.java @@ -33,7 +33,8 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity httpS "/swagger-ui/**", "/swagger", "/error", - "/swagger-ui.html" + "/h2/**", + "/member/**" ).permitAll().anyExchange().authenticated()) .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(jwtSpec -> jwtSpec.authenticationManager(jwtReactiveAuthenticationManager))) .build(); diff --git a/examples/reactive-rest-example/src/main/resources/application-local.yml b/examples/reactive-rest-example/src/main/resources/application-local.yml index 94f1ea3900a..403f11ba4ba 100644 --- a/examples/reactive-rest-example/src/main/resources/application-local.yml +++ b/examples/reactive-rest-example/src/main/resources/application-local.yml @@ -1,10 +1,17 @@ +TOKEN_X_ISSUER: nada + spring: application: # Override name name: reactive-rest-example-local + h2: + console: + enabled: true + path: /h2 flyway: # InMemmory database url: jdbc:h2:mem:testdb username: sa - password: \ No newline at end of file + password: + driverClassName: org.h2.Driver \ No newline at end of file diff --git a/libs/servlet-insecure-security/build.gradle b/libs/servlet-insecure-security/build.gradle index 21a166d7a93..d212cb034ad 100644 --- a/libs/servlet-insecure-security/build.gradle +++ b/libs/servlet-insecure-security/build.gradle @@ -16,6 +16,5 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' } \ No newline at end of file diff --git a/proxies/pdl-proxy/config.yml b/proxies/pdl-proxy/config.yml index a044b13b15d..b5a88f48086 100644 --- a/proxies/pdl-proxy/config.yml +++ b/proxies/pdl-proxy/config.yml @@ -19,8 +19,8 @@ metadata: labels: team: dolly annotations: - nginx.ingress.kubernetes.io/proxy-read-timeout: "600" - nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "2400" + nginx.ingress.kubernetes.io/proxy-send-timeout: "2400" spec: image: "{{image}}" port: 8080