Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
44688ad
Refactor KodeverkConsumer
bjornhun Oct 15, 2024
8691b8a
Bumps, refactor, kotest-assertions, fjernet ubrukt autocomplete-felt
bjornhun Oct 16, 2024
7ad3d11
Fjernet token-validering da vi ikke bruker dette
bjornhun Oct 16, 2024
02cfb89
Forbedret integrasjonstester (json-compare), bruker clock-bønne for å…
bjornhun Oct 17, 2024
ef4bcb0
Slanket integrasjonstest-kode litt, returnerer 204 og ingen body på s…
bjornhun Oct 17, 2024
d1f4e3b
Cleanup
bjornhun Oct 17, 2024
ac5b506
Refactor
bjornhun Oct 18, 2024
67fb20b
Fjernet ubrukt keywords-felt
bjornhun Oct 18, 2024
9d4bc6a
Refactor + flere tester for InboundMapper
bjornhun Oct 22, 2024
8b761f1
Mer refactor
bjornhun Oct 22, 2024
8d3cda4
Bruker factory-funksjon i stedet for secondary constructor i Content …
bjornhun Oct 22, 2024
cc1a748
Kotest i validator-tester
bjornhun Oct 22, 2024
036b088
Refactor validator
bjornhun Oct 22, 2024
fe8c147
Fjernet doble linjeskift
bjornhun Oct 22, 2024
10e83a3
Deskriptive navn på tester
bjornhun Oct 22, 2024
646fe87
Bump opensearch-versjon i lib
bjornhun Oct 22, 2024
96b7d5a
Ekstra test og fjernet redundant kode
bjornhun Oct 22, 2024
1386e92
Stor forbokstav i filnavn
bjornhun Oct 22, 2024
24f9ce1
Stor forbokstav i filnavn
bjornhun Oct 22, 2024
f69e4bd
Default argument på includeTypeInAllText
bjornhun Oct 23, 2024
7419344
Merge branch 'main' of https://github.com/navikt/navno-search-admin-a…
bjornhun Nov 11, 2024
c19677c
Index name bump
bjornhun Nov 11, 2024
1ec3e68
Bump spring boot
bjornhun Nov 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
val kotlinVersion = "2.0.20"
val springBootVersion = "3.3.3"
val springBootVersion = "3.3.5"
val springDepMgmtVersion = "1.1.6"
val versionsVersion = "0.51.0"

Expand All @@ -24,16 +24,15 @@ repositories {
}

dependencies {
val navSecurityVersion = "5.0.5"
val logstashVersion = "8.0"
val opensearchVersion = "1.5.2"
val opensearchVersion = "1.5.3"
val jsoupVersion = "1.18.1"
val opensearchTestcontainersVersion = "2.1.0"
val testcontainersVersion = "1.20.1"
val opensearchTestcontainersVersion = "2.1.1"
val testcontainersVersion = "1.20.2"
val wiremockVersion = "4.1.4"
val kotestVersion = "5.9.1"

implementation(project(":lib"))
implementation("no.nav.security:token-validation-spring:$navSecurityVersion")
implementation("org.opensearch.client:spring-data-opensearch-starter:$opensearchVersion") {
exclude("org.opensearch.client", "opensearch-rest-client-sniffer")
}
Expand All @@ -46,14 +45,15 @@ dependencies {
implementation("io.micrometer:micrometer-registry-prometheus")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jsoup:jsoup:$jsoupVersion")
testImplementation("no.nav.security:token-validation-spring-test:$navSecurityVersion")
testImplementation("org.opensearch.client:spring-data-opensearch-test-autoconfigure:$opensearchVersion") {
exclude("org.opensearch.client", "opensearch-rest-client-sniffer")
}
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.cloud:spring-cloud-contract-wiremock:$wiremockVersion")
testImplementation("org.testcontainers:junit-jupiter:$testcontainersVersion")
testImplementation("org.opensearch:opensearch-testcontainers:$opensearchTestcontainersVersion")
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
testImplementation("io.kotest:kotest-assertions-json:$kotestVersion")
}

tasks.withType<KotlinCompile> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package no.nav.navnosearchadminapi.config

import no.nav.security.token.support.spring.api.EnableJwtTokenValidation
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.client.RestTemplate

import java.time.Clock

@Configuration
@EnableCaching
@EnableJwtTokenValidation
class ApplicationConfig {
@Bean
fun restTemplate(builder: RestTemplateBuilder): RestTemplate? {
return builder.build()
}

@Bean
fun clock(): Clock {
return Clock.systemDefaultZone()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,24 @@ class KodeverkConsumer(
@Cacheable("spraakkoder")
fun fetchSpraakKoder(): KodeverkResponse {
try {
val response = restTemplate.exchange(
kodeverkUrl,
HttpMethod.GET,
HttpEntity<Any>(headers()),
KodeverkResponse::class.java
)
return response.body ?: throw KodeverkConsumerException("Tom response body fra kodeverk-api")
return azureADConsumer.getAccessToken(kodeverkScope).let { accessToken ->
restTemplate.exchange(
kodeverkUrl,
HttpMethod.GET,
HttpEntity<Any>(headers(accessToken)),
KodeverkResponse::class.java
)
}.body ?: throw KodeverkConsumerException("Tom response body fra kodeverk-api")
} catch (e: HttpStatusCodeException) {
throw KodeverkConsumerException("Feil ved kall til kodeverk-api. ${e.message}", e)
}
}

private fun headers(): HttpHeaders {
return azureADConsumer.getAccessToken(kodeverkScope).let { accessToken ->
HttpHeaders().apply {
setBearerAuth(accessToken)
set(NAV_CALL_ID, UUID.randomUUID().toString())
set(NAV_CONSUMER_ID, NAVNO_SEARCH_ADMIN_API)
}
private fun headers(accessToken: String): HttpHeaders {
return HttpHeaders().apply {
setBearerAuth(accessToken)
set(NAV_CALL_ID, UUID.randomUUID().toString())
set(NAV_CONSUMER_ID, NAVNO_SEARCH_ADMIN_API)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ data class ContentMetadata(
val fylke: String? = null,
val metatags: List<String> = emptyList(),
val languageRefs: List<String> = emptyList(),
val keywords: List<String> = emptyList()
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
package no.nav.navnosearchadminapi.exception

class TokenFetchException(message: String, cause: Throwable) : Exception(message, cause) {
}
class TokenFetchException(message: String, cause: Throwable) : Exception(message, cause)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package no.nav.navnosearchadminapi.exception.handler
import jakarta.servlet.http.HttpServletRequest
import no.nav.navnosearchadminapi.exception.InvalidApiKeyException
import no.nav.navnosearchadminapi.exception.MissingIdException
import no.nav.security.token.support.spring.validation.interceptor.JwtTokenUnauthorizedException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.event.Level
Expand All @@ -12,27 +11,14 @@ import org.springframework.http.ResponseEntity
import org.springframework.web.bind.MissingServletRequestParameterException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import java.time.LocalDateTime

import java.time.Clock
import java.time.ZonedDateTime

@ControllerAdvice
class ErrorHandler {
class ErrorHandler(val clock: Clock) {

val logger: Logger = LoggerFactory.getLogger(ErrorHandler::class.java)

@ExceptionHandler(value = [JwtTokenUnauthorizedException::class])
fun jwtTokenUnauthorizedHandler(
ex: JwtTokenUnauthorizedException,
request: HttpServletRequest
): ResponseEntity<ErrorResponse> {
return handleException(
status = HttpStatus.UNAUTHORIZED,
message = "Validering av token feilet",
path = request.requestURI,
ex = ex
)
}

@ExceptionHandler(value = [InvalidApiKeyException::class])
fun invalidApiKeyHandler(
ex: InvalidApiKeyException,
Expand Down Expand Up @@ -89,7 +75,7 @@ class ErrorHandler {
ex: Throwable
): ResponseEntity<ErrorResponse> {
val error = ErrorResponse(
timestamp = LocalDateTime.now(),
timestamp = ZonedDateTime.now(clock),
status = status.value(),
error = status.reasonPhrase,
message = message ?: ex.message,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package no.nav.navnosearchadminapi.exception.handler

import java.time.LocalDateTime
import java.time.ZonedDateTime

data class ErrorResponse(
val timestamp: LocalDateTime,
val timestamp: ZonedDateTime,
val status: Int,
val error: String,
val message: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import no.nav.navnosearchadminapi.dto.inbound.ContentDto
import no.nav.navnosearchadminapi.dto.outbound.SaveContentResponse
import no.nav.navnosearchadminapi.rest.aspect.ApiKeyProtected
import no.nav.navnosearchadminapi.service.AdminService
import no.nav.security.token.support.spring.UnprotectedRestController
import org.springframework.data.domain.Page
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController

@UnprotectedRestController
@RestController
class AdminController(val service: AdminService) {

@PostMapping("/content/{teamName}")
Expand All @@ -36,8 +38,8 @@ class AdminController(val service: AdminService) {

@DeleteMapping("/content/{teamName}/{id}")
@ApiKeyProtected
fun deleteContentByTeamNameAndId(@PathVariable teamName: String, @PathVariable id: String): String {
@ResponseStatus(HttpStatus.NO_CONTENT)
fun deleteContentByTeamNameAndId(@PathVariable teamName: String, @PathVariable id: String) {
service.deleteContentByTeamNameAndId(teamName, id)
return "Dokument med id $id slettet"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ import org.springframework.stereotype.Component
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes


@Aspect
@Component
class HeaderCheckAspect(@Value("\${api-key}") val apiKey: String) {

@Before("@annotation(apiKeyProtected)")
fun checkHeader(apiKeyProtected: ApiKeyProtected) {

val request = (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes).request

val actualValue = request.getHeader(API_KEY_HEADER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package no.nav.navnosearchadminapi.service
import no.nav.navnosearchadminapi.common.repository.ContentRepository
import no.nav.navnosearchadminapi.dto.inbound.ContentDto
import no.nav.navnosearchadminapi.dto.outbound.SaveContentResponse
import no.nav.navnosearchadminapi.service.mapper.ContentDtoMapper
import no.nav.navnosearchadminapi.service.mapper.ContentMapper
import no.nav.navnosearchadminapi.service.mapper.toInbound
import no.nav.navnosearchadminapi.service.mapper.toOutbound
import no.nav.navnosearchadminapi.service.validation.ContentDtoValidator
import no.nav.navnosearchadminapi.utils.createInternalId
import org.slf4j.Logger
Expand All @@ -17,8 +17,6 @@ import org.springframework.stereotype.Service
@Service
class AdminService(
val validator: ContentDtoValidator,
val contentDtoMapper: ContentDtoMapper,
val contentMapper: ContentMapper,
val repository: ContentRepository,
@Value("\${opensearch.page-size}") val pageSize: Int,
) {
Expand All @@ -33,7 +31,7 @@ class AdminService(

val mappedContent = content
.filter { !validationErrors.containsKey(it.id) }
.map { contentMapper.toContent(it, teamName) }
.map { it.toInbound(teamName) }
repository.saveAll(mappedContent)

val numberOfIndexedDocuments = mappedContent.size
Expand All @@ -54,6 +52,6 @@ class AdminService(

fun getContentForTeamName(teamName: String, page: Int): Page<ContentDto> {
val pageable = PageRequest.of(page, pageSize)
return repository.findAllByTeamOwnedBy(teamName, pageable).map { contentDtoMapper.toContentDto(it) }
return repository.findAllByTeamOwnedBy(teamName, pageable).map { it.toOutbound() }
}
}

This file was deleted.

Loading
Loading