From dd4a87b3ec859fe682c529c8803a56f8d7f5666a Mon Sep 17 00:00:00 2001 From: Stian Gustavsson Date: Tue, 27 Aug 2024 09:03:41 +0200 Subject: [PATCH] Bugfix/dolly idporten issues (#3593) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fikset error ved avhuking av mal i idporten * Fjernet fysiskDokument fra maler og lagt til test for dette * Endret litt på playwrigt oppsett * Endret kodeverk-service til å støtte token fra idporten og route denne korrekt videre til kodeverk-api * Tillater kun navigering til tenoridenter for bankid brukere og skrevet tester for NavigasjonService * Fikset navigering i idporten og gamle identer fra før prodlast og tester rundt denne funksjonaliteten --- .../dolly/DollyBackendApplicationStarter.java | 2 +- .../strategy/TestgruppeMappingStrategy.java | 31 +-- .../provider/api/TestgruppeController.java | 14 +- .../provider/api/TestpersonController.java | 11 +- .../nav/dolly/service/BestillingService.java | 45 ++-- .../dolly/service/MalBestillingService.java | 11 +- .../nav/dolly/service/NavigasjonService.java | 38 ++-- .../java/no/nav/dolly/util/IdentTypeUtil.java | 12 + .../java/no/nav/dolly/util/TokenXUtil.java | 2 +- .../src/main/resources/application.yaml | 3 + .../TestgruppeMappingStrategyTest.java | 8 +- .../mapper/strategy/TestidentMappingTest.java | 3 +- .../api/MalBestillingControllerTest.java | 117 ++++++++-- .../api/TestgruppeControllerDeleteTest.java | 2 - .../dolly/service/NavigasjonServiceTest.java | 205 ++++++++++++++++++ .../src/main/js/playwright.config.js | 7 +- .../tenorSoek/resultatVisning/MalValg.tsx | 4 +- apps/kodeverk-service/build.gradle | 17 +- apps/kodeverk-service/settings.gradle | 3 +- .../kodeverkservice/config/AppConfig.java | 8 +- .../kodeverkservice/config/OpenApiConfig.java | 25 +-- .../config/SecurityConfig.java | 41 ++-- .../consumer/KodeverkConsumer.java | 2 +- .../servletsecurity/action/GetUserInfo.java | 5 +- 24 files changed, 456 insertions(+), 160 deletions(-) create mode 100644 apps/dolly-backend/src/test/java/no/nav/dolly/service/NavigasjonServiceTest.java diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/DollyBackendApplicationStarter.java b/apps/dolly-backend/src/main/java/no/nav/dolly/DollyBackendApplicationStarter.java index 6af8668f777..f0ef428e58d 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/DollyBackendApplicationStarter.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/DollyBackendApplicationStarter.java @@ -10,4 +10,4 @@ public static void main(String[] args) { SpringApplication.run(DollyBackendApplicationStarter.class, args); } -} \ No newline at end of file +} diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategy.java b/apps/dolly-backend/src/main/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategy.java index ab8bd4c9d62..7361700298f 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategy.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategy.java @@ -9,13 +9,9 @@ import no.nav.dolly.domain.resultset.Tags; import no.nav.dolly.domain.resultset.entity.testgruppe.RsTestgruppe; import no.nav.dolly.mapper.MappingStrategy; -import no.nav.testnav.libs.servletsecurity.action.GetUserInfo; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import static java.util.Objects.nonNull; -import static no.nav.dolly.util.CurrentAuthentication.getUserId; import static org.apache.commons.lang3.BooleanUtils.isTrue; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -23,17 +19,6 @@ @RequiredArgsConstructor public class TestgruppeMappingStrategy implements MappingStrategy { - private final GetUserInfo getUserInfo; - - private static String getBrukerId(Bruker bruker) { - - if (isNotBlank(bruker.getBrukerId())) { - return bruker.getBrukerId(); - } else { - return nonNull(bruker.getEidAv()) ? bruker.getEidAv().getBrukerId() : bruker.getNavIdent(); - } - } - @Override public void register(MapperFactory factory) { factory.classMap(Testgruppe.class, RsTestgruppe.class) @@ -41,17 +26,12 @@ public void register(MapperFactory factory) { @Override public void mapAtoB(Testgruppe testgruppe, RsTestgruppe rsTestgruppe, MappingContext context) { - var securityContext = (SecurityContext) context.getProperty("securityContext"); - if (nonNull(securityContext)) { - SecurityContextHolder.setContext(securityContext); - } - rsTestgruppe.setAntallIdenter(testgruppe.getTestidenter().size()); rsTestgruppe.setAntallIBruk((int) testgruppe.getTestidenter().stream() .filter(ident -> isTrue(ident.getIBruk())) .count()); rsTestgruppe.setFavorittIGruppen(!testgruppe.getFavorisertAv().isEmpty()); - rsTestgruppe.setErEierAvGruppe(getUserId(getUserInfo).equals(getBrukerId(testgruppe.getOpprettetAv()))); + rsTestgruppe.setErEierAvGruppe(nonNull(context.getProperty("brukerId")) && (context.getProperty("brukerId")).equals(getBrukerId(testgruppe.getOpprettetAv()))); rsTestgruppe.setErLaast(isTrue(rsTestgruppe.getErLaast())); rsTestgruppe.setTags(testgruppe.getTags().stream() .filter(tag -> Tags.DOLLY != tag) @@ -62,4 +42,13 @@ public void mapAtoB(Testgruppe testgruppe, RsTestgruppe rsTestgruppe, MappingCon .byDefault() .register(); } + + private static String getBrukerId(Bruker bruker) { + + if (isNotBlank(bruker.getBrukerId())) { + return bruker.getBrukerId(); + } else { + return nonNull(bruker.getEidAv()) ? bruker.getEidAv().getBrukerId() : bruker.getNavIdent(); + } + } } \ No newline at end of file diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestgruppeController.java b/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestgruppeController.java index da740694bae..59eae5e60ff 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestgruppeController.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestgruppeController.java @@ -93,7 +93,7 @@ public RsTestgruppe oppdaterTestgruppeLaas(@PathVariable("gruppeId") Long gruppe return mapperFacade.map(gruppe, RsTestgruppe.class); } - @CacheEvict(value = {CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_GRUPPE }, allEntries = true) @PostMapping @Transactional @ResponseStatus(HttpStatus.CREATED) @@ -155,7 +155,7 @@ public void slettgruppe(@PathVariable("gruppeId") Long gruppeId) { testgruppeService.deleteGruppeById(gruppeId); } - @CacheEvict(value = {CACHE_BESTILLING, CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_BESTILLING, CACHE_GRUPPE }, allEntries = true) @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{gruppeId}/bestilling") @Operation(description = "Opprett berikede testpersoner basert på fødselsdato, kjønn og identtype") @@ -167,7 +167,7 @@ public RsBestillingStatus opprettIdentBestilling(@PathVariable("gruppeId") Long } @Operation(description = "Opprett berikede testpersoner basert på eskisterende identer") - @CacheEvict(value = {CACHE_BESTILLING, CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_BESTILLING, CACHE_GRUPPE }, allEntries = true) @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{gruppeId}/bestilling/fraidenter") public RsBestillingStatus opprettIdentBestillingFraIdenter(@PathVariable("gruppeId") Long gruppeId, @RequestBody RsDollyBestillingFraIdenterRequest request) { @@ -179,7 +179,7 @@ public RsBestillingStatus opprettIdentBestillingFraIdenter(@PathVariable("gruppe } @Operation(description = "Importere testpersoner fra PDL og legg til berikning non-PDL artifacter") - @CacheEvict(value = {CACHE_BESTILLING, CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_BESTILLING, CACHE_GRUPPE }, allEntries = true) @ResponseStatus(HttpStatus.CREATED) @PostMapping("/{gruppeId}/bestilling/importfrapdl") public RsBestillingStatus importAvIdenterFraPdlBestilling(@PathVariable("gruppeId") Long gruppeId, @RequestBody RsDollyImportFraPdlRequest request) { @@ -191,7 +191,7 @@ public RsBestillingStatus importAvIdenterFraPdlBestilling(@PathVariable("gruppeI } @Operation(description = "Legg til berikning på alle i gruppe") - @CacheEvict(value = {CACHE_BESTILLING, CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_BESTILLING, CACHE_GRUPPE }, allEntries = true) @ResponseStatus(HttpStatus.OK) @PutMapping("/{gruppeId}/leggtilpaagruppe") public RsBestillingStatus endreGruppeLeggTil(@PathVariable("gruppeId") Long gruppeId, @RequestBody RsDollyBestillingLeggTilPaaGruppe request) { @@ -201,7 +201,7 @@ public RsBestillingStatus endreGruppeLeggTil(@PathVariable("gruppeId") Long grup return mapperFacade.map(bestilling, RsBestillingStatus.class); } - @CacheEvict(value = {CACHE_BESTILLING, CACHE_GRUPPE}, allEntries = true) + @CacheEvict(value = { CACHE_BESTILLING, CACHE_GRUPPE }, allEntries = true) @PutMapping("/{gruppeId}/gjenopprett") @Operation(description = "Gjenopprett testidenter tilhørende en gruppe med liste for tilhørende miljoer") public RsBestillingStatus gjenopprettBestilling(@PathVariable("gruppeId") Long gruppeId, @@ -212,7 +212,7 @@ public RsBestillingStatus gjenopprettBestilling(@PathVariable("gruppeId") Long g return mapperFacade.map(bestilling, RsBestillingStatus.class); } - @CacheEvict(value = {CACHE_GRUPPE, CACHE_BESTILLING}, allEntries = true) + @CacheEvict(value = { CACHE_GRUPPE, CACHE_BESTILLING }, allEntries = true) @Transactional @PutMapping(value = "/{gruppeId}/identer/{identer}") @Operation(description = "Flytt angitte identer til denne gruppe") diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestpersonController.java b/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestpersonController.java index eb17aa4dd80..485607ef926 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestpersonController.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/provider/api/TestpersonController.java @@ -5,9 +5,9 @@ import ma.glasnost.orika.MapperFacade; import no.nav.dolly.bestilling.service.GjenopprettIdentService; import no.nav.dolly.bestilling.service.OppdaterPersonService; -import no.nav.testnav.libs.dto.dolly.v1.FinnesDTO; import no.nav.dolly.domain.dto.TestidentDTO; import no.nav.dolly.domain.jpa.Bestilling; +import no.nav.dolly.domain.jpa.Bruker; import no.nav.dolly.domain.resultset.RsDollyUpdateRequest; import no.nav.dolly.domain.resultset.RsIdentBeskrivelse; import no.nav.dolly.domain.resultset.entity.bestilling.RsBestillingStatus; @@ -16,11 +16,14 @@ import no.nav.dolly.domain.testperson.IdentAttributesResponse; import no.nav.dolly.exceptions.NotFoundException; import no.nav.dolly.service.BestillingService; +import no.nav.dolly.service.BrukerService; import no.nav.dolly.service.IdentService; import no.nav.dolly.service.NavigasjonService; import no.nav.dolly.service.OrdreService; import no.nav.dolly.service.PersonService; import no.nav.dolly.service.TransaksjonMappingService; +import no.nav.testnav.libs.dto.dolly.v1.FinnesDTO; +import no.nav.testnav.libs.servletsecurity.action.GetUserInfo; import org.springframework.cache.annotation.CacheEvict; import org.springframework.http.HttpStatus; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +45,7 @@ import static java.util.Objects.nonNull; import static no.nav.dolly.config.CachingConfig.CACHE_BESTILLING; import static no.nav.dolly.config.CachingConfig.CACHE_GRUPPE; +import static no.nav.dolly.util.CurrentAuthentication.getUserId; @RestController @RequiredArgsConstructor @@ -54,9 +58,11 @@ public class TestpersonController { private final OppdaterPersonService oppdaterPersonService; private final MapperFacade mapperFacade; private final IdentService identService; + private final BrukerService brukerService; private final PersonService personService; private final NavigasjonService navigasjonService; private final OrdreService ordreService; + private final GetUserInfo getUserInfo; @Operation(description = "Legge til egenskaper på person/endre person i TPS og øvrige systemer") @PutMapping("/{ident}/leggtilpaaperson") @@ -133,7 +139,8 @@ public void deleteTestident(@PathVariable String ident) { @GetMapping("/naviger/{ident}") public Mono navigerTilTestident(@PathVariable String ident) { - return navigasjonService.navigerTilIdent(ident); + Bruker bruker = brukerService.fetchBruker(getUserId(getUserInfo)); + return navigasjonService.navigerTilIdent(ident, bruker); } @Operation(description = "Sjekk om ønsket testperson finnes i Dolly") diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/service/BestillingService.java b/apps/dolly-backend/src/main/java/no/nav/dolly/service/BestillingService.java index 5164bcb4f63..576e0c57d2f 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/service/BestillingService.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/service/BestillingService.java @@ -30,7 +30,6 @@ import no.nav.dolly.repository.TestgruppeRepository; import no.nav.testnav.libs.servletsecurity.action.GetUserInfo; import org.apache.commons.lang3.StringUtils; -import org.hibernate.StaleStateException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -52,6 +51,7 @@ import static java.lang.String.join; import static java.time.LocalDateTime.now; import static java.util.Collections.emptySet; +import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static java.util.stream.Collectors.toSet; import static no.nav.dolly.util.CurrentAuthentication.getUserId; @@ -140,7 +140,7 @@ public Page getBestillingerFromGruppeIdPaginert(Long gruppeId, Integ } @Transactional - @Retryable(StaleStateException.class) + @Retryable public Bestilling cancelBestilling(Long bestillingId) { var bestillingKontroll = bestillingKontrollRepository.findByBestillingId(bestillingId); @@ -214,19 +214,6 @@ public Bestilling saveBestilling(RsDollyUpdateRequest request, String ident) { return saveBestillingToDB(bestilling); } - private String filterAvailable(Collection environments) { - - var miljoer = miljoerConsumer.getMiljoer().block(); - return nonNull(environments) ? environments.stream() - .filter(miljoer::contains) - .collect(Collectors.joining(",")) : null; - } - - private String filterAvailable(String miljoer) { - - return isNotBlank(miljoer) ? filterAvailable(Arrays.asList(miljoer.split(","))) : null; - } - @Transactional public Bestilling saveBestilling(Long gruppeId, RsDollyBestilling request, Integer antall, List opprettFraIdenter, Boolean navSyntetiskIdent, String beskrivelse) { @@ -273,7 +260,6 @@ public Bestilling createBestillingForGjenopprettFraBestilling(Long bestillingId, .build()); } - @Transactional // Egen transaksjon på denne da bestillingId hentes opp igjen fra database i samme kallet public Bestilling createBestillingForGjenopprettFraIdent(String ident, Testgruppe testgruppe, List miljoer) { @@ -426,6 +412,28 @@ public String getBestKriterier(RsDollyBestilling request) { .build()); } + public List getProgressByBestillingId(Long bestillingId) { + + return bestillingProgressRepository.findByBestilling_Id(bestillingId); + } + + private String filterAvailable(Collection environments) { + + var miljoer = miljoerConsumer.getMiljoer().block(); + + if (isNull(miljoer)) { + return null; + } + return environments.stream() + .filter(miljoer::contains) + .collect(Collectors.joining(",")); + } + + private String filterAvailable(String miljoer) { + + return isNotBlank(miljoer) ? filterAvailable(Arrays.asList(miljoer.split(","))) : null; + } + private String wrapSearchString(String searchString) { return isNotBlank(searchString) ? "%%%s%%".formatted(searchString) : ""; } @@ -454,9 +462,4 @@ private static void fixAaregAbstractClassProblem(List aaregdata) { } }); } - - public List getProgressByBestillingId(Long bestillingId) { - - return bestillingProgressRepository.findByBestilling_Id(bestillingId); - } } \ No newline at end of file diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/service/MalBestillingService.java b/apps/dolly-backend/src/main/java/no/nav/dolly/service/MalBestillingService.java index e24d4b9e27b..3e122762ffa 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/service/MalBestillingService.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/service/MalBestillingService.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import ma.glasnost.orika.MapperFacade; import no.nav.dolly.domain.jpa.Bestilling; import no.nav.dolly.domain.jpa.BestillingMal; @@ -38,6 +39,7 @@ import static no.nav.dolly.util.CurrentAuthentication.getUserId; @Service +@Slf4j @RequiredArgsConstructor public class MalBestillingService { @@ -89,6 +91,7 @@ public RsMalBestillingWrapper getMalBestillinger() { .toList()); return malBestillingWrapper; + } @Transactional(readOnly = true) @@ -132,7 +135,7 @@ public void saveBestillingMal(Bestilling bestilling, String malNavn, Bruker bruk if (eksisterende.isEmpty()) { bestillingMalRepository.save(BestillingMal.builder() - .bestKriterier(bestilling.getBestKriterier()) + .bestKriterier(formatBestillingKriterier(bestilling.getBestKriterier())) .bruker(bruker) .malNavn(malNavn) .miljoer(bestilling.getMiljoer()) @@ -159,7 +162,7 @@ public RsMalBestilling saveBestillingMalFromBestillingId(Long bestillingId, Stri var maler = bestillingMalRepository.findByBrukerAndMalNavn(bruker, malNavn); if (maler.isEmpty()) { malbestilling = bestillingMalRepository.save(BestillingMal.builder() - .bestKriterier(bestilling.getBestKriterier()) + .bestKriterier(formatBestillingKriterier(bestilling.getBestKriterier())) .bruker(bruker) .malNavn(malNavn) .miljoer(bestilling.getMiljoer()) @@ -270,6 +273,10 @@ private RsDollyUtvidetBestilling fromJson(String json) { } } + private String formatBestillingKriterier(String bestillingKriterier) { + return bestillingKriterier.replaceAll("fysiskDokument[^,]*+,", ""); + } + private static Set toSet(String miljoer) { return StringUtils.isNotBlank(miljoer) ? diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/service/NavigasjonService.java b/apps/dolly-backend/src/main/java/no/nav/dolly/service/NavigasjonService.java index dce039152a5..f14625fe317 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/service/NavigasjonService.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/service/NavigasjonService.java @@ -7,6 +7,7 @@ import no.nav.dolly.bestilling.personservice.PersonServiceConsumer; import no.nav.dolly.domain.PdlPerson; import no.nav.dolly.domain.PdlPersonBolk; +import no.nav.dolly.domain.jpa.Bruker; import no.nav.dolly.domain.jpa.Testgruppe; import no.nav.dolly.domain.resultset.entity.testgruppe.RsTestgruppe; import no.nav.dolly.domain.resultset.entity.testident.RsWhereAmI; @@ -18,8 +19,6 @@ import no.nav.testnav.libs.data.pdlforvalter.v1.KontaktinformasjonForDoedsboDTO; import no.nav.testnav.libs.data.pdlforvalter.v1.SivilstandDTO; import no.nav.testnav.libs.data.pdlforvalter.v1.VergemaalDTO; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; @@ -27,11 +26,11 @@ import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.function.Function; import java.util.stream.Stream; import static java.util.Objects.nonNull; +import static no.nav.dolly.util.IdentTypeUtil.isTenorIdent; @Service @RequiredArgsConstructor @@ -47,18 +46,16 @@ public class NavigasjonService { private final PdlDataConsumer pdlDataConsumer; @Transactional(readOnly = true) - public Mono navigerTilIdent(String ident) { + public Mono navigerTilIdent(String ident, Bruker bruker) { - var securityContext = SecurityContextHolder.getContext(); return Flux.merge(getPdlForvalterIdenter(ident), getPdlPersonIdenter(ident)) .filter(Objects::nonNull) + .filter(ident1 -> filterOnBrukertype(ident, bruker.getBrukertype())) .distinct() - .flatMap(ident1 -> Mono.just(identRepository.findByIdent(ident1)) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(ident1 -> Mono.justOrEmpty(identRepository.findByIdent(ident1)) .map(testident -> RsWhereAmI.builder() - .gruppe(mapGruppe(testident.getTestgruppe(), securityContext)) + .gruppe(mapGruppe(testident.getTestgruppe(), bruker.getBrukerId())) .identHovedperson(testident.getIdent()) .identNavigerTil(ident) .sidetall(Math.floorDiv( @@ -69,16 +66,9 @@ public Mono navigerTilIdent(String ident) { .next(); } - private RsTestgruppe mapGruppe(Testgruppe testgruppe, SecurityContext securityContext) { - - var context = new MappingContext.Factory().getContext(); - context.setProperty("securityContext", securityContext); - return mapperFacade.map(testgruppe, RsTestgruppe.class, context); - } - public Mono navigerTilBestilling(Long bestillingId) { - return Mono.just(bestillingService.fetchBestillingById(bestillingId)) + return Mono.justOrEmpty(bestillingService.fetchBestillingById(bestillingId)) .map(bestilling -> RsWhereAmI.builder() .bestillingNavigerTil(bestillingId) .gruppe(mapperFacade.map(bestilling.getGruppe(), RsTestgruppe.class)) @@ -89,6 +79,20 @@ public Mono navigerTilBestilling(Long bestillingId) { .switchIfEmpty(Mono.error(() -> new NotFoundException(String.format(IKKE_FUNNET, bestillingId)))); } + private boolean filterOnBrukertype(String ident, Bruker.Brukertype brukertype) { + if (brukertype == Bruker.Brukertype.BANKID) { + return isTenorIdent(ident); + } + return true; + } + + private RsTestgruppe mapGruppe(Testgruppe testgruppe, String brukerId) { + + var context = new MappingContext.Factory().getContext(); + context.setProperty("brukerId", brukerId); + return mapperFacade.map(testgruppe, RsTestgruppe.class, context); + } + private Flux getPdlPersonIdenter(String ident) { return personServiceConsumer.getPdlPersoner(List.of(ident)) diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/util/IdentTypeUtil.java b/apps/dolly-backend/src/main/java/no/nav/dolly/util/IdentTypeUtil.java index 728458bcc11..802949460f7 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/util/IdentTypeUtil.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/util/IdentTypeUtil.java @@ -31,4 +31,16 @@ public static boolean isSyntetisk(String ident) { return isNotBlank(ident) && ident.length() == 11 && Integer.parseInt(ident.substring(2, 3)) >= 4; } + + public static boolean isDollyIdent(String ident) { + + return isSyntetisk(ident) && + ident.substring(2, 3).matches("[4,5]"); + } + + public static boolean isTenorIdent(String ident) { + + return isSyntetisk(ident) && + ident.substring(2, 3).matches("[8,9]"); + } } diff --git a/apps/dolly-backend/src/main/java/no/nav/dolly/util/TokenXUtil.java b/apps/dolly-backend/src/main/java/no/nav/dolly/util/TokenXUtil.java index fa6bab4e0d5..6a3d17bbafc 100644 --- a/apps/dolly-backend/src/main/java/no/nav/dolly/util/TokenXUtil.java +++ b/apps/dolly-backend/src/main/java/no/nav/dolly/util/TokenXUtil.java @@ -43,7 +43,7 @@ public static UserInfo getBankidUser(GetUserInfo getUserInfo) { return getUserInfo.call() .orElse(null); } catch (NullPointerException e) { - log.info("Fant ikke BankID request"); + log.info("Fant ikke BankID brukerinfo"); return null; } } diff --git a/apps/dolly-backend/src/main/resources/application.yaml b/apps/dolly-backend/src/main/resources/application.yaml index f2bb53a8d5d..054493fae3c 100644 --- a/apps/dolly-backend/src/main/resources/application.yaml +++ b/apps/dolly-backend/src/main/resources/application.yaml @@ -48,6 +48,9 @@ spring: issuer-uri: ${AAD_ISSUER_URI}/v2.0 jwk-set-uri: ${AAD_ISSUER_URI}/discovery/v2.0/keys accepted-audience: ${azure.app.client.id}, api://${azure.app.client.id} + jackson: + parser: + include-source-in-location: true springdoc: swagger-ui: diff --git a/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategyTest.java b/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategyTest.java index 742699674c8..b24b18e177e 100644 --- a/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategyTest.java +++ b/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestgruppeMappingStrategyTest.java @@ -10,7 +10,6 @@ import no.nav.dolly.domain.resultset.entity.testident.RsTestident; import no.nav.dolly.elastic.BestillingElasticRepository; import no.nav.dolly.mapper.utils.MapperTestUtils; -import no.nav.testnav.libs.servletsecurity.action.GetUserInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -29,19 +28,16 @@ @SpringBootTest class TestgruppeMappingStrategyTest { + private final static String BRUKERID = "123"; @MockBean private BestillingElasticRepository bestillingElasticRepository; - @MockBean private ElasticsearchOperations elasticsearchOperations; - - private final static String BRUKERID = "123"; - private MapperFacade mapper; @BeforeEach public void setUpHappyPath() { - mapper = MapperTestUtils.createMapperFacadeForMappingStrategy(new TestgruppeMappingStrategy(new GetUserInfo("dummy"))); + mapper = MapperTestUtils.createMapperFacadeForMappingStrategy(new TestgruppeMappingStrategy()); MockedJwtAuthenticationTokenUtils.setJwtAuthenticationToken(); } diff --git a/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestidentMappingTest.java b/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestidentMappingTest.java index 50927b6d33a..30e50f657d5 100644 --- a/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestidentMappingTest.java +++ b/apps/dolly-backend/src/test/java/no/nav/dolly/mapper/strategy/TestidentMappingTest.java @@ -7,7 +7,6 @@ import no.nav.dolly.domain.jpa.Testident; import no.nav.dolly.domain.resultset.entity.testident.RsTestident; import no.nav.dolly.mapper.utils.MapperTestUtils; -import no.nav.testnav.libs.servletsecurity.action.GetUserInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -22,7 +21,7 @@ class TestidentMappingTest { @BeforeEach public void setUpHappyPath() { - mapper = MapperTestUtils.createMapperFacadeForMappingStrategy(new TestgruppeMappingStrategy(new GetUserInfo("dummy"))); + mapper = MapperTestUtils.createMapperFacadeForMappingStrategy(new TestgruppeMappingStrategy()); } @Test diff --git a/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/MalBestillingControllerTest.java b/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/MalBestillingControllerTest.java index 2879d3ae1ba..88b6f3758e5 100644 --- a/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/MalBestillingControllerTest.java +++ b/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/MalBestillingControllerTest.java @@ -1,5 +1,6 @@ package no.nav.dolly.provider.api; +import com.github.tomakehurst.wiremock.common.Json; import no.nav.dolly.MockedJwtAuthenticationTokenUtils; import no.nav.dolly.domain.jpa.Bestilling; import no.nav.dolly.domain.jpa.BestillingMal; @@ -30,13 +31,16 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.not; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -48,17 +52,41 @@ @AutoConfigureMockMvc(addFilters = false) class MalBestillingControllerTest { - @MockBean - @SuppressWarnings("unused") - private BestillingElasticRepository bestillingElasticRepository; - - @MockBean - @SuppressWarnings("unused") - private ElasticsearchOperations elasticsearchOperations; + private static final String MALNAVN = "test"; + private static final String NYTT_MALNAVN = "nyttMalnavn"; + private static final String BEST_KRITERIER = "{\"test\":true}"; + private static final String BEST_KRITERIER_FORMATERT = Json.write(""" + { + "pdldata": { + "opprettNyPerson": null, + "person": null + }, + "dokarkiv": { + "tittel": "Generell fullmakt", + "tema": "PEN", + "kanal": "NAV_NO", + "avsenderMottaker": { + "id": "123456789012", + "idType": "FNR", + "navn": "Lun overgang" + }, + "dokumenter": [ + { + "tittel": "dokument.pdf", + "brevkode": "BREV123", + "dokumentvarianter": [ + { + "filtype": "PDFA", + "fysiskDokument": "AWDHAWDIui23u21h", + "variantformat": "ARKIV" + } + ] + } + ] + } + } + """); - private final static String MALNAVN = "test"; - private final static String NYTT_MALNAVN = "nyttMalnavn"; - private final static String BEST_KRITERIER = "{\"test\":true}"; private static final Bruker DUMMY_EN = Bruker.builder() .brukerId("testbruker_en") .brukernavn("test_en") @@ -77,12 +105,17 @@ class MalBestillingControllerTest { .brukertype(Bruker.Brukertype.AZURE) .epost("epost@test_tre") .build(); + private static final String IDENT = "12345678912"; private static final String BESKRIVELSE = "Teste"; private static final String TESTGRUPPE = "Testgruppe"; private static final String UGYLDIG_BESTILLINGID = "999"; - - + @MockBean + @SuppressWarnings("unused") + private BestillingElasticRepository bestillingElasticRepository; + @MockBean + @SuppressWarnings("unused") + private ElasticsearchOperations elasticsearchOperations; @Autowired private MockMvc mockMvc; @Autowired @@ -117,10 +150,10 @@ public void afterEach() { void shouldCreateAndGetMaler() throws Exception { - var bruker_en = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); - var bruker_to = brukerRepository.findBrukerByBrukerId(DUMMY_TO.getBrukerId()).orElseThrow(); - saveDummyBestillingMal(bruker_en); - saveDummyBestillingMal(bruker_to); + var brukerEn = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); + var brukerTo = brukerRepository.findBrukerByBrukerId(DUMMY_TO.getBrukerId()).orElseThrow(); + saveDummyBestillingMal(brukerEn); + saveDummyBestillingMal(brukerTo); mockMvc.perform(get("/api/v1/malbestilling")) .andExpect(status().isOk()) @@ -128,8 +161,8 @@ void shouldCreateAndGetMaler() .andExpect(jsonPath("$.malbestillinger.test_en", hasSize(1))) .andExpect(jsonPath("$.malbestillinger.test_to", hasSize(1))) .andExpect(jsonPath("$.malbestillinger.test_en[0].malNavn").value(MALNAVN)) - .andExpect(jsonPath("$.malbestillinger.test_en[0].bruker.brukerId").value(bruker_en.getBrukerId())) - .andExpect(jsonPath("$.malbestillinger.test_to[0].bruker.brukerId").value(bruker_to.getBrukerId())); + .andExpect(jsonPath("$.malbestillinger.test_en[0].bruker.brukerId").value(brukerEn.getBrukerId())) + .andExpect(jsonPath("$.malbestillinger.test_to[0].bruker.brukerId").value(brukerTo.getBrukerId())); } @Test @@ -138,9 +171,9 @@ void shouldCreateAndGetMaler() void shouldCreateMalerFromExistingOrder() throws Exception { - var bruker_en = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); + var brukerEn = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); var testgruppe = saveDummyGruppe(); - var bestilling = saveDummyBestilling(bruker_en, testgruppe); + var bestilling = saveDummyBestilling(brukerEn, testgruppe); mockMvc.perform(post("/api/v1/malbestilling") .queryParam("bestillingId", String.valueOf(bestilling.getId())) @@ -153,14 +186,37 @@ void shouldCreateMalerFromExistingOrder() .andExpect(status().is4xxClientError()); } + @Test + @Transactional + @DisplayName("Oppretter mal fra gjeldende bestilling og tester at NotFoundError blir kastet ved ugyldig bestillingId") + void shouldCreateFormatertMalFromExistingOrder() + throws Exception { + + var brukerEn = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); + var testgruppe = saveDummyGruppe(); + var bestilling = saveDummyBestillingMedFormaterteKriterier(brukerEn, testgruppe); + + mockMvc.perform(post("/api/v1/malbestilling") + .queryParam("bestillingId", String.valueOf(bestilling.getId())) + .queryParam("malNavn", MALNAVN)) + .andExpect((content().string(not("fysiskDokument")))) + .andExpect((content().string(containsString("variantformat")))) + .andExpect(status().isOk()); + + mockMvc.perform(post("/api/v1/malbestilling") + .queryParam("bestillingId", UGYLDIG_BESTILLINGID) + .queryParam("malNavn", MALNAVN)) + .andExpect(status().is4xxClientError()); + } + @Test @Transactional @DisplayName("Oppretter, endrer navn på og sletter til slutt bestillingMal") void shouldCreateUpdateAndDeleteMal() throws Exception { - var bruker_en = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); - var bestillingMal = saveDummyBestillingMal(bruker_en); + var brukerEn = brukerRepository.findBrukerByBrukerId(DUMMY_EN.getBrukerId()).orElseThrow(); + var bestillingMal = saveDummyBestillingMal(brukerEn); mockMvc.perform(put("/api/v1/malbestilling/id/{id}", bestillingMal.getId()) .queryParam("malNavn", NYTT_MALNAVN)) @@ -208,6 +264,23 @@ Bestilling saveDummyBestilling(Bruker bruker, Testgruppe testgruppe) { ); } + Bestilling saveDummyBestillingMedFormaterteKriterier(Bruker bruker, Testgruppe testgruppe) { + return bestillingRepository.save( + Bestilling + .builder() + .gruppe(testgruppe) + .ferdig(false) + .antallIdenter(1) + .bestKriterier(BEST_KRITERIER_FORMATERT) + .bruker(bruker) + .beskrivelse(BESKRIVELSE) + .sistOppdatert(LocalDateTime.now()) + .ident(IDENT) + .navSyntetiskIdent(true) + .build() + ); + } + Testgruppe saveDummyGruppe() { return testgruppeRepository.save( Testgruppe.builder() diff --git a/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/TestgruppeControllerDeleteTest.java b/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/TestgruppeControllerDeleteTest.java index 427cc6a1e1c..3a80bdca67a 100644 --- a/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/TestgruppeControllerDeleteTest.java +++ b/apps/dolly-backend/src/test/java/no/nav/dolly/provider/api/TestgruppeControllerDeleteTest.java @@ -32,7 +32,5 @@ void deleteTestgruppe() .perform(get("/api/v1/gruppe/{id}", testgruppe.getId())) .andExpect(status().isNotFound()); assertThat(super.findTestgruppeById(testgruppe.getId())).isEmpty(); - } - } diff --git a/apps/dolly-backend/src/test/java/no/nav/dolly/service/NavigasjonServiceTest.java b/apps/dolly-backend/src/test/java/no/nav/dolly/service/NavigasjonServiceTest.java new file mode 100644 index 00000000000..3b5a71e268e --- /dev/null +++ b/apps/dolly-backend/src/test/java/no/nav/dolly/service/NavigasjonServiceTest.java @@ -0,0 +1,205 @@ +package no.nav.dolly.service; + +import ma.glasnost.orika.MapperFacade; +import no.nav.dolly.bestilling.pdldata.PdlDataConsumer; +import no.nav.dolly.bestilling.personservice.PersonServiceConsumer; +import no.nav.dolly.domain.PdlPersonBolk; +import no.nav.dolly.domain.jpa.Bestilling; +import no.nav.dolly.domain.jpa.Bruker; +import no.nav.dolly.domain.jpa.Testgruppe; +import no.nav.dolly.domain.jpa.Testident; +import no.nav.dolly.domain.resultset.entity.testgruppe.RsTestgruppe; +import no.nav.dolly.domain.resultset.entity.testident.RsWhereAmI; +import no.nav.dolly.exceptions.NotFoundException; +import no.nav.dolly.repository.IdentRepository; +import no.nav.testnav.libs.data.pdlforvalter.v1.FullPersonDTO; +import no.nav.testnav.libs.data.pdlforvalter.v1.PersonDTO; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +class NavigasjonServiceTest { + + @Mock + private IdentRepository identRepository; + + @Mock + private IdentService identService; + + @Mock + private BestillingService bestillingService; + + @Mock + private MapperFacade mapperFacade; + + @Mock + private PersonServiceConsumer personServiceConsumer; + + @Mock + private PdlDataConsumer pdlDataConsumer; + + @InjectMocks + private NavigasjonService navigasjonService; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testNavigerTilIdentFound() { + String ident = "12445678901"; + RsWhereAmI expected = RsWhereAmI.builder() + .identHovedperson(ident) + .identNavigerTil(ident) + .build(); + + Testident testident = Testident.builder() + .ident(ident) + .testgruppe( + Testgruppe.builder() + .id(1L) + .build() + ).build(); + + FullPersonDTO fullPersonDTO = FullPersonDTO.builder() + .person(PersonDTO.builder().ident(ident).build()) + .build(); + + when(identRepository.findByIdent(any())).thenReturn(Optional.of(testident)); + when(identService.getPaginertIdentIndex(any(), any())).thenReturn(Optional.of(1)); + when(mapperFacade.map(any(), eq(RsWhereAmI.class))).thenReturn(expected); + when(pdlDataConsumer.getPersoner(any())).thenReturn(Flux.just(fullPersonDTO)); + when(personServiceConsumer.getPdlPersoner(any())).thenReturn(Flux.just(PdlPersonBolk.builder().build())); + + Mono result = navigasjonService.navigerTilIdent(ident, Bruker.builder().brukertype(Bruker.Brukertype.AZURE).build()); + + StepVerifier.create(result) + .expectNext(expected) + .verifyComplete(); + } + + @Test + void testBankidUserNavigerTilIdentAllowed() { + String identAllowed = "12881212345"; + + RsWhereAmI expected = RsWhereAmI.builder() + .identHovedperson(identAllowed) + .identNavigerTil(identAllowed) + .build(); + + Testident tiAllowed = Testident.builder() + .ident(identAllowed) + .testgruppe( + Testgruppe.builder() + .id(1L) + .build() + ).build(); + + FullPersonDTO fpAllowed = FullPersonDTO.builder() + .person(PersonDTO.builder().ident(identAllowed).build()) + .build(); + + when(identRepository.findByIdent(eq(identAllowed))).thenReturn(Optional.of(tiAllowed)); + + when(identService.getPaginertIdentIndex(any(), any())).thenReturn(Optional.of(1)); + when(mapperFacade.map(any(), eq(RsWhereAmI.class))).thenReturn(RsWhereAmI.builder().identHovedperson(identAllowed).build()); + when(pdlDataConsumer.getPersoner(any())).thenReturn(Flux.just(fpAllowed)); + when(personServiceConsumer.getPdlPersoner(any())).thenReturn(Flux.just(PdlPersonBolk.builder().build())); + + Mono result = navigasjonService.navigerTilIdent(identAllowed, Bruker.builder().brukertype(Bruker.Brukertype.BANKID).build()); + + StepVerifier.create(result) + .expectNext(expected) + .verifyComplete(); + } + + @Test + void testBankidUserNavigerTilIdentRefused() { + String identRefused = "12441212345"; + + Testident tiRefused = Testident.builder() + .ident(identRefused) + .testgruppe( + Testgruppe.builder() + .id(1L) + .build() + ).build(); + + FullPersonDTO fpRefused = FullPersonDTO.builder() + .person(PersonDTO.builder().ident(identRefused).build()) + .build(); + + when(identRepository.findByIdent(eq(identRefused))).thenReturn(Optional.of(tiRefused)); + + when(identService.getPaginertIdentIndex(any(), any())).thenReturn(Optional.of(1)); + when(mapperFacade.map(any(), eq(RsWhereAmI.class))).thenReturn(RsWhereAmI.builder().identHovedperson(identRefused).build()); + when(pdlDataConsumer.getPersoner(any())).thenReturn(Flux.just(fpRefused)); + when(personServiceConsumer.getPdlPersoner(any())).thenReturn(Flux.just(PdlPersonBolk.builder().build())); + + Mono result = navigasjonService.navigerTilIdent(identRefused, Bruker.builder().brukertype(Bruker.Brukertype.BANKID).build()); + + StepVerifier.create(result) + .expectError(NotFoundException.class) + .verify(); + } + + @Test + void testNavigerTilIdentNotFound() { + String ident = "12445678901"; + + when(identRepository.findByIdent(any())).thenReturn(Optional.empty()); + when(pdlDataConsumer.getPersoner(any())).thenReturn(Flux.empty()); + when(personServiceConsumer.getPdlPersoner(any())).thenReturn(Flux.empty()); + + Mono result = navigasjonService.navigerTilIdent(ident, Bruker.builder().brukertype(Bruker.Brukertype.AZURE).build()); + + StepVerifier.create(result) + .expectError(NotFoundException.class) + .verify(); + } + + @Test + void testNavigerTilBestillingFound() { + Long bestillingId = 1L; + + Testgruppe testgruppe = new Testgruppe(); + + Bestilling bestilling = new Bestilling(); + bestilling.setGruppe(testgruppe); + + when(bestillingService.fetchBestillingById(any())).thenReturn(bestilling); + when(bestillingService.getPaginertBestillingIndex(any(), any())).thenReturn(Optional.of(1)); + when(mapperFacade.map(any(Testgruppe.class), eq(RsTestgruppe.class))).thenReturn(new RsTestgruppe()); + + Mono result = navigasjonService.navigerTilBestilling(bestillingId); + + StepVerifier.create(result) + .expectNextMatches(rsWhereAmI -> rsWhereAmI.getBestillingNavigerTil().equals(bestillingId)) + .verifyComplete(); + } + + @Test + void testNavigerTilBestillingNotFound() { + Long bestillingId = 1L; + + when(bestillingService.fetchBestillingById(any())).thenReturn(null); + + Mono result = navigasjonService.navigerTilBestilling(bestillingId); + + StepVerifier.create(result) + .expectError(NotFoundException.class) + .verify(); + } +} \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/js/playwright.config.js b/apps/dolly-frontend/src/main/js/playwright.config.js index e56c24f3f73..21a11bd1ed9 100644 --- a/apps/dolly-frontend/src/main/js/playwright.config.js +++ b/apps/dolly-frontend/src/main/js/playwright.config.js @@ -14,10 +14,9 @@ export default defineConfig({ /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - // Fewer workers on CI to make tests more stable - workers: process.env.CI ? 2 : undefined, + retries: process.env.CI ? 2 : 1, + // One worker on CI to make tests more stable + workers: process.env.CI ? 1 : 3, reporter: 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ diff --git a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/MalValg.tsx b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/MalValg.tsx index b783e47e505..8bc62c45299 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/MalValg.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/MalValg.tsx @@ -15,7 +15,7 @@ const MalValgWrapper = styled.div` ` const getBrukerOptions = (malbestillinger: any) => - Object.keys(malbestillinger).map((ident) => ({ + Object.keys(malbestillinger)?.map((ident) => ({ value: ident, label: ident, })) @@ -24,7 +24,7 @@ const getMalOptions = (malbestillinger: any, bruker: any) => { if (!malbestillinger || !malbestillinger[bruker]) { return [] } - return malbestillinger[bruker].map((mal: any) => ({ + return malbestillinger?.[bruker]?.map((mal: any) => ({ value: mal.id, label: mal.malNavn, data: { bestilling: mal.bestilling, malNavn: mal.malNavn }, diff --git a/apps/kodeverk-service/build.gradle b/apps/kodeverk-service/build.gradle index 4aeeb607350..56d1d5fe8fc 100644 --- a/apps/kodeverk-service/build.gradle +++ b/apps/kodeverk-service/build.gradle @@ -12,17 +12,26 @@ sonarqube { dependencies { implementation 'no.nav.testnav.libs:security-core' + implementation 'no.nav.testnav.libs:servlet-core' implementation 'no.nav.testnav.libs:reactive-core' - implementation 'no.nav.testnav.libs:reactive-security' + implementation 'no.nav.testnav.libs:servlet-insecure-security' implementation 'no.nav.testnav.libs:data-transfer-objects' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-cache' + implementation 'org.springframework.cloud:spring-cloud-starter-vault-config' + implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation "org.springdoc:springdoc-openapi-starter-webflux-ui:$versions.springdoc" + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:$versions.springdoc" implementation "io.swagger.core.v3:swagger-annotations-jakarta:$versions.swagger" + implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + + implementation 'org.springframework.boot:spring-boot-starter-cache' + implementation 'com.github.ben-manes.caffeine:caffeine' } diff --git a/apps/kodeverk-service/settings.gradle b/apps/kodeverk-service/settings.gradle index b0f70bc2265..7b680dfe7ba 100644 --- a/apps/kodeverk-service/settings.gradle +++ b/apps/kodeverk-service/settings.gradle @@ -7,8 +7,9 @@ rootProject.name = 'kodeverk-service' includeBuild "../../plugins/java" includeBuild '../../libs/data-transfer-objects' +includeBuild '../../libs/servlet-core' includeBuild '../../libs/reactive-core' -includeBuild '../../libs/reactive-security' +includeBuild '../../libs/servlet-insecure-security' includeBuild '../../libs/security-core' develocity { diff --git a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/AppConfig.java b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/AppConfig.java index d5872c6c2cf..c852de3e91a 100644 --- a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/AppConfig.java +++ b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/AppConfig.java @@ -1,14 +1,14 @@ package no.nav.testnav.kodeverkservice.config; -import no.nav.testnav.libs.reactivecore.config.CoreConfig; -import no.nav.testnav.libs.reactivesecurity.config.SecureOAuth2ServerToServerConfiguration; +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; @Configuration @Import({ - CoreConfig.class, - SecureOAuth2ServerToServerConfiguration.class + ApplicationCoreConfig.class, + InsecureJwtServerToServerConfiguration.class }) public class AppConfig { } diff --git a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/OpenApiConfig.java b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/OpenApiConfig.java index 61352dbec8d..e80ff3fbcfe 100644 --- a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/OpenApiConfig.java +++ b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/OpenApiConfig.java @@ -7,19 +7,16 @@ 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.reactivecore.config.ApplicationProperties; +import no.nav.testnav.libs.servletcore.config.ApplicationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -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 org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Arrays; @Configuration -public class OpenApiConfig implements WebFilter { +public class OpenApiConfig implements WebMvcConfigurer { @Bean public OpenAPI openApi(ApplicationProperties applicationProperties) { @@ -29,7 +26,7 @@ public OpenAPI openApi(ApplicationProperties applicationProperties) { .scheme("bearer") .bearerFormat("JWT") .in(SecurityScheme.In.HEADER) - .name(HttpHeaders.AUTHORIZATION) + .name("Authorization") )) .addSecurityItem( new SecurityRequirement().addList("bearer-jwt", Arrays.asList("read", "write"))) @@ -51,15 +48,7 @@ public OpenAPI openApi(ApplicationProperties applicationProperties) { } @Override - 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); + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger").setViewName("redirect:/swagger-ui.html"); } } \ No newline at end of file diff --git a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/SecurityConfig.java b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/SecurityConfig.java index 20c8c0c96af..be2ddd5da90 100644 --- a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/SecurityConfig.java +++ b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/config/SecurityConfig.java @@ -1,38 +1,37 @@ package no.nav.testnav.kodeverkservice.config; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -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.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; +import org.springframework.context.annotation.Profile; +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.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; -@Slf4j +@EnableWebSecurity @Configuration -@EnableWebFluxSecurity -@EnableReactiveMethodSecurity -@RequiredArgsConstructor +@Profile({ "prod", "dev" }) public class SecurityConfig { - private final JwtReactiveAuthenticationManager jwtReactiveAuthenticationManager; - @Bean - public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity httpSecurity) { - return httpSecurity - .csrf(ServerHttpSecurity.CsrfSpec::disable) - .authorizeExchange(authorizeConfig -> authorizeConfig.pathMatchers( + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + + httpSecurity.sessionManagement(sessionConfig -> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorizeConfig -> authorizeConfig.requestMatchers( "/internal/**", "/webjars/**", + "/swagger-resources/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger", "/error", "/swagger-ui.html" - ).permitAll().anyExchange().authenticated()) - .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(jwtSpec -> jwtSpec.authenticationManager(jwtReactiveAuthenticationManager))) - .build(); + ).permitAll().requestMatchers("/api/**").fullyAuthenticated()) + .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(Customizer.withDefaults())); + + return httpSecurity.build(); } -} \ No newline at end of file +} diff --git a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/consumer/KodeverkConsumer.java b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/consumer/KodeverkConsumer.java index d8ec625f15a..0365ecc0250 100644 --- a/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/consumer/KodeverkConsumer.java +++ b/apps/kodeverk-service/src/main/java/no/nav/testnav/kodeverkservice/consumer/KodeverkConsumer.java @@ -4,8 +4,8 @@ import no.nav.testnav.kodeverkservice.consumer.command.KodeverkGetCommand; import no.nav.testnav.kodeverkservice.dto.KodeverkBetydningerResponse; import no.nav.testnav.kodeverkservice.utility.FilterUtility; -import no.nav.testnav.libs.reactivesecurity.exchange.TokenExchange; import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.ExchangeStrategies; import org.springframework.web.reactive.function.client.WebClient; diff --git a/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/action/GetUserInfo.java b/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/action/GetUserInfo.java index 9d1399ab534..52a7b4cdcff 100644 --- a/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/action/GetUserInfo.java +++ b/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/action/GetUserInfo.java @@ -25,7 +25,10 @@ public GetUserInfo(@Value("${JWT_SECRET:#{null}}") String secret) { @Override public Optional call() { - var request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + var requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + + var request = requestAttributes.getRequest(); log.trace("Prøver å hente JWT fra request..."); return Optional.ofNullable(request.getHeader(UserConstant.USER_HEADER_JWT)).map(token -> { log.trace("Fant JWT i request.");