Skip to content

Commit

Permalink
Merge pull request #269 from navikt/v2api
Browse files Browse the repository at this point in the history
Meldekort API v2
  • Loading branch information
igorweber authored Jun 3, 2024
2 parents 892dd87 + 49cf0fe commit 0cccb84
Show file tree
Hide file tree
Showing 13 changed files with 453 additions and 21 deletions.
12 changes: 3 additions & 9 deletions .nais/nais.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ metadata:
labels:
team: meldekort
spec:
azure:
application:
enabled: true
claims:
extra:
- "azp_name"
image: {{image}}
port: 8090
prometheus:
Expand Down Expand Up @@ -51,14 +45,14 @@ spec:
requests:
cpu: 500m
memory: 2Gi
env:
- name: TOKEN_X_ACCEPTED_AUDIENCE
value: '{{ tokenxAcceptedAudience }}'
tokenx:
enabled: true
accessPolicy:
inbound:
rules:
- application: tokenx-token-generator
namespace: aura
cluster: dev-gcp
- application: meldekort-api{{ dashEnv }}
namespace: meldekort
cluster: {{ vaultServiceuserEnv }}-gcp
Expand Down
1 change: 0 additions & 1 deletion .nais/vars-p.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ vaultKvEnv: prod/fss
vaultServiceuserEnv: prod
ingresses:
- "https://meldekortservice.prod-fss-pub.nais.io"
tokenxAcceptedAudience: prod-fss:meldekort:meldekortservice
1 change: 0 additions & 1 deletion .nais/vars-q1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ vaultKvEnv: preprod/fss
vaultServiceuserEnv: dev
ingresses:
- "https://meldekortservice-q1.dev-fss-pub.nais.io"
tokenxAcceptedAudience: dev-fss:meldekort:meldekortservice-q1
1 change: 0 additions & 1 deletion .nais/vars-q2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ vaultKvEnv: preprod/fss
vaultServiceuserEnv: dev
ingresses:
- "https://meldekortservice-q2.dev-fss-pub.nais.io"
tokenxAcceptedAudience: dev-fss:meldekort:meldekortservice-q2
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Det er også mulig å kjøre `gradle clean build`, men da må man ha en riktig v
2. Start appen ved å kjøre `./gradlew runServerTest`.
Det er også mulig å kjøre Server.kt sin main-metode eller `./gradlew runServer`, men da må man sette miljøvariablene:
TOKEN_X_WELL_KNOWN_URL
TOKEN_X_ACCEPTED_AUDIENCE
TOKEN_X_CLIENT_ID
For å kjøre mot f.eks Q1 kan man enten sette riktige miljøvariabler (manuelt eller ved hjelp av bat/bash script) eller midlertidig skrive disse inn i Environment.kt i stedet for defaultValue'er.
For eksempel, for å bruke ORDS i Q1 må man erstatte
```
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ tasks {

register("runServerTest", JavaExec::class) {
systemProperties["TOKEN_X_WELL_KNOWN_URL"] = "tokenx.dev.nav.no"
systemProperties["TOKEN_X_ACCEPTED_AUDIENCE"] = "nav.no"
systemProperties["TOKEN_X_CLIENT_ID"] = "test:meldekort:meldekortservice"

mainClass.set(project.property("mainClassName").toString())
classpath = sourceSets["main"].runtimeClasspath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ fun Routing.getKorrigertMeldekort(arenaOrdsService: ArenaOrdsService) =
) { korrigertMeldekortInput ->
respondOrError {

val meldekortdetaljer = arenaOrdsService.hentMeldekortdetaljer(korrigertMeldekortInput.meldekortId)
if (meldekortdetaljer.fodselsnr != userIdent) {
val msg = "Personidentifikator matcher ikke. Bruker kan derfor ikke korrigere meldekort."
defaultLog.warn(msg)
throw SecurityException()
}

arenaOrdsService.kopierMeldekort(korrigertMeldekortInput.meldekortId)
}
}
156 changes: 156 additions & 0 deletions src/main/kotlin/no/nav/meldeplikt/meldekortservice/api/MeldekortV2.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package no.nav.meldeplikt.meldekortservice.api

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.locations.*
import io.ktor.server.routing.*
import no.nav.meldeplikt.meldekortservice.model.feil.NoContentException
import no.nav.meldeplikt.meldekortservice.model.meldekort.Person
import no.nav.meldeplikt.meldekortservice.model.meldekortdetaljer.Meldekortdetaljer
import no.nav.meldeplikt.meldekortservice.service.ArenaOrdsService
import no.nav.meldeplikt.meldekortservice.utils.*
import no.nav.meldeplikt.meldekortservice.utils.swagger.*

/**
* REST-controller som henter FNR fra ident-header og tilbyr operasjoner for å hente:
* - Meldekort
* - Historiske meldekort
* - Meldekortdetaljer
* - Korrigert meldekort (ber Arena å opprette et nytt meldekort basert på meldekort med angitt ID og returnerer ny ID)
*/

class Headers(val ident: String)

@KtorExperimentalLocationsAPI
fun Routing.meldekortApiV2(arenaOrdsService: ArenaOrdsService) {
hentMeldekort(arenaOrdsService)
hentHistoriskeMeldekort(arenaOrdsService)
hentMeldekortdetaljer(arenaOrdsService)
hentKorrigertMeldekort(arenaOrdsService)
}

private const val group = "Meldekort v2"

@Group(group)
@Location("$API_PATH/v2/meldekort")
@KtorExperimentalLocationsAPI
class HentMeldekortInput

@KtorExperimentalLocationsAPI
fun Routing.hentMeldekort(arenaOrdsService: ArenaOrdsService) = get<HentMeldekortInput>(
"Hent meldekort".securityAndResponse(
BearerTokenSecurity(),
ok<Person>(),
badRequest<ErrorMessage>(),
serviceUnavailable<ErrorMessage>(),
unAuthorized<Error>()
).header<Headers>()
) {
respondOrError {
val ident = getIdent(call)

val response = arenaOrdsService.hentMeldekort(ident)
if (response.status == HttpStatusCode.OK) {
mapFraXml(response.content, Person::class.java)
} else {
throw NoContentException()
}
}
}

@Group(group)
@Location("$API_PATH/v2/historiskemeldekort")
@KtorExperimentalLocationsAPI
class HentHistoriskeMeldekortInput(val antallMeldeperioder: Int)

@KtorExperimentalLocationsAPI
fun Routing.hentHistoriskeMeldekort(arenaOrdsService: ArenaOrdsService) = get<HentHistoriskeMeldekortInput>(
"Hent tidligere/historiske meldekort".securityAndResponse(
BearerTokenSecurity(),
ok<Person>(),
badRequest<ErrorMessage>(),
serviceUnavailable<ErrorMessage>(),
unAuthorized<Error>()
).header<Headers>()
) { hentHistoriskeMeldekortInput ->
respondOrError {
val ident = getIdent(call)

arenaOrdsService.hentHistoriskeMeldekort(
ident,
hentHistoriskeMeldekortInput.antallMeldeperioder
)
}
}

@Group(group)
@Location("$API_PATH/v2/meldekortdetaljer")
@KtorExperimentalLocationsAPI
data class HentMeldekortdetaljerInput(val meldekortId: Long)

@KtorExperimentalLocationsAPI
fun Routing.hentMeldekortdetaljer(arenaOrdsService: ArenaOrdsService) =
get<HentMeldekortdetaljerInput>(
"Hent meldekortdetaljer".securityAndResponse(
BearerTokenSecurity(),
ok<Meldekortdetaljer>(),
badRequest<ErrorMessage>(),
serviceUnavailable<ErrorMessage>(),
unAuthorized<Error>()
).header<Headers>()
) { hentMeldekortdetaljerInput ->
respondOrError {
val ident = getIdent(call)

val meldekortdetaljer = arenaOrdsService.hentMeldekortdetaljer(hentMeldekortdetaljerInput.meldekortId)
if (meldekortdetaljer.meldegruppe == "") meldekortdetaljer.meldegruppe = "NULL"
if (meldekortdetaljer.fodselsnr == ident) {
meldekortdetaljer
} else {
val msg = "Personidentifikator matcher ikke. Bruker kan derfor ikke hente ut meldekortdetaljer."
defaultLog.warn(msg)
throw SecurityException(msg)
}
}
}

@Group(group)
@Location("$API_PATH/v2/korrigertMeldekort")
@KtorExperimentalLocationsAPI
data class HentKorrigertMeldekortInput(
val meldekortId: Long
)

@KtorExperimentalLocationsAPI
fun Routing.hentKorrigertMeldekort(arenaOrdsService: ArenaOrdsService) =
get<HentKorrigertMeldekortInput>(
"Hent korrigert meldekortid".securityAndResponse(
BearerTokenSecurity(),
ok<String>(),
badRequest<ErrorMessage>(),
serviceUnavailable<ErrorMessage>(),
unAuthorized<Error>()
).header<Headers>()
) { hentKorrigertMeldekortInput ->
respondOrError {
val ident = getIdent(call)

val meldekortdetaljer = arenaOrdsService.hentMeldekortdetaljer(hentKorrigertMeldekortInput.meldekortId)
if (meldekortdetaljer.fodselsnr != ident) {
val msg = "Personidentifikator matcher ikke. Bruker kan derfor ikke korrigere meldekort."
defaultLog.warn(msg)
throw SecurityException()
}

arenaOrdsService.kopierMeldekort(hentKorrigertMeldekortInput.meldekortId)
}
}

private fun getIdent(call: ApplicationCall): String {
val ident = call.request.headers["ident"]
if (ident.isNullOrBlank() || ident.length != 11) {
throw SecurityException("Personidentifikator finnes ikke")
}

return ident
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ fun Application.mainModule(
skrivemodusApi(arenaOrdsService)
meldekortApi(arenaOrdsService)
personApi(arenaOrdsService)
meldekortApiV2(arenaOrdsService)
}

install(DoubleReceive) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ no.nav.security.jwt {
{
issuer_name = "tokenx"
discoveryurl = ${TOKEN_X_WELL_KNOWN_URL}
accepted_audience = ${TOKEN_X_ACCEPTED_AUDIENCE}
accepted_audience = ${TOKEN_X_CLIENT_ID}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ class MeldekortKtTest : TestBase() {
assertEquals(HttpStatusCode.Unauthorized, response.status)
}

@Test
fun `get korrigert meldekortid returns 400 Bad Request with invalid ident`() = setUpTestApplication {
val id: Long = 1
val nyId: Long = 123
val meldekortdetaljer = Meldekortdetaljer(
id = "1",
fodselsnr = "01020312346",
kortType = KortType.AAP
)

coEvery { arenaOrdsService.kopierMeldekort(any()) } returns (nyId)
coEvery { arenaOrdsService.hentMeldekortdetaljer(any()) } returns (meldekortdetaljer)

val response = client.get("/meldekortservice/api/meldekort/korrigering?meldekortId=${id}") {
header(HttpHeaders.Authorization, "Bearer ${issueTokenWithPid()}")
}

assertEquals(HttpStatusCode.BadRequest, response.status)
}

@Test
fun `get meldekortdetaljer returns 401-Unauthorized with invalid JWT`() = setUpTestApplication {
val id: Long = 1
Expand All @@ -115,8 +135,14 @@ class MeldekortKtTest : TestBase() {
fun `get korrigert meldekortid returns OK with valid JWT with sub`() = setUpTestApplication {
val id: Long = 1
val nyId: Long = 123
val meldekortdetaljer = Meldekortdetaljer(
id = "1",
fodselsnr = DUMMY_FNR,
kortType = KortType.AAP
)

coEvery { arenaOrdsService.kopierMeldekort(any()) } returns (nyId)
coEvery { arenaOrdsService.hentMeldekortdetaljer(any()) } returns (meldekortdetaljer)

val response = client.get("/meldekortservice/api/meldekort/korrigering?meldekortId=${id}") {
header(HttpHeaders.Authorization, "Bearer ${issueTokenWithSub()}")
Expand All @@ -132,8 +158,14 @@ class MeldekortKtTest : TestBase() {
fun `get korrigert meldekortid returns OK with valid JWT with pid`() = setUpTestApplication {
val id: Long = 1
val nyId: Long = 123
val meldekortdetaljer = Meldekortdetaljer(
id = "1",
fodselsnr = DUMMY_FNR,
kortType = KortType.AAP
)

coEvery { arenaOrdsService.kopierMeldekort(any()) } returns (nyId)
coEvery { arenaOrdsService.hentMeldekortdetaljer(any()) } returns (meldekortdetaljer)

val response = client.get("/meldekortservice/api/meldekort/korrigering?meldekortId=${id}") {
header(HttpHeaders.Authorization, "Bearer ${issueTokenWithPid()}")
Expand Down
Loading

0 comments on commit 0cccb84

Please sign in to comment.