Skip to content

Commit

Permalink
/api/userInfo/v2
Browse files Browse the repository at this point in the history
  • Loading branch information
kenglxn committed Oct 10, 2024
1 parent ef24231 commit 7cf956b
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package no.nav.arbeidsgiver.min_side.services.altinn

import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
Expand All @@ -26,7 +27,7 @@ class AltinnService(
@Value("\${nais.cluster.name}") private val naisCluster: String,
) {

private val cache: Cache<String, AltinnTilgangerResponse> = Caffeine.newBuilder()
private val cache: Cache<String, AltinnTilganger> = Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats()
Expand All @@ -43,26 +44,20 @@ class AltinnService(
)
).build()

fun hentOrganisasjoner(): List<Organisasjon> {
val altinnTilganger = hentAltinnTilganger()
val organisasjoner = altinnTilganger.hierarki.flatMap { flattenUnderOrganisasjoner(it) }
return organisasjoner
}

fun hentAltinnTilganger(): AltinnTilgangerResponse =
fun hentAltinnTilganger() =
cache.getIfPresent(authenticatedUserHolder.token) ?: run {
hentAltinnTilgangerFraProxy().also {
cache.put(authenticatedUserHolder.token, it)
}
}

fun harTilgang(orgnr: String, tjeneste: String) =
hentAltinnTilganger().orgNrTilTilganger[orgnr]?.contains(tjeneste) ?: false
fun hentOrganisasjoner() = hentAltinnTilganger().organisasjonerFlattened

fun harOrganisasjon(orgnr: String) =
hentOrganisasjoner().any { it.organizationNumber == orgnr }
fun harTilgang(orgnr: String, tjeneste: String) = hentAltinnTilganger().harTilgang(orgnr, tjeneste)

private fun hentAltinnTilgangerFraProxy(): AltinnTilgangerResponse {
fun harOrganisasjon(orgnr: String) = hentAltinnTilganger().harOrganisasjon(orgnr)

private fun hentAltinnTilgangerFraProxy(): AltinnTilganger {
val token = tokenExchangeClient.exchange(
authenticatedUserHolder.token,
"$naisCluster:fager:arbeidsgiver-altinn-tilganger"
Expand All @@ -75,30 +70,16 @@ class AltinnService(
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer $token")
.build(),
AltinnTilgangerResponse::class.java
AltinnTilganger::class.java
)

return response.body!! // response != 200 => throws
}

private fun flattenUnderOrganisasjoner(
altinnTilgang: AltinnTilgangerResponse.AltinnTilgang,
parentOrgNr: String? = null
): List<Organisasjon> {
val parent = Organisasjon(
name = altinnTilgang.name,
parentOrganizationNumber = parentOrgNr,
organizationForm = altinnTilgang.organizationForm,
organizationNumber = altinnTilgang.orgNr
)
val children = altinnTilgang.underenheter.flatMap { flattenUnderOrganisasjoner(it, parent.organizationNumber) }
return listOf(parent) + children
}
}


@JsonIgnoreProperties(ignoreUnknown = true)
data class AltinnTilgangerResponse(
data class AltinnTilganger(
val isError: Boolean,
val hierarki: List<AltinnTilgang>,
val orgNrTilTilganger: Map<String, Set<String>>,
Expand All @@ -112,5 +93,28 @@ data class AltinnTilgangerResponse(
val name: String,
val organizationForm: String,
)

@get:JsonIgnore
val organisasjonerFlattened : List<Organisasjon>
get() = hierarki.flatMap { flattenUnderOrganisasjoner(it) }

fun harOrganisasjon(orgnr: String) =
organisasjonerFlattened.any { it.organizationNumber == orgnr }

fun harTilgang(orgnr: String, tjeneste: String) = orgNrTilTilganger[orgnr]?.contains(tjeneste) ?: false

private fun flattenUnderOrganisasjoner(
altinnTilgang: AltinnTilgang,
parentOrgNr: String? = null
): List<Organisasjon> {
val parent = Organisasjon(
name = altinnTilgang.name,
parentOrganizationNumber = parentOrgNr,
organizationForm = altinnTilgang.organizationForm,
organizationNumber = altinnTilgang.orgNr
)
val children = altinnTilgang.underenheter.flatMap { flattenUnderOrganisasjoner(it, parent.organizationNumber) }
return listOf(parent) + children
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.coroutines.supervisorScope
import no.nav.arbeidsgiver.min_side.controller.AuthenticatedUserHolder
import no.nav.arbeidsgiver.min_side.models.Organisasjon
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnService
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnTilganger
import no.nav.arbeidsgiver.min_side.services.digisyfo.DigisyfoService
import no.nav.arbeidsgiver.min_side.services.digisyfo.DigisyfoService.VirksomhetOgAntallSykmeldte
import no.nav.arbeidsgiver.min_side.services.tiltak.RefusjonStatusService
Expand All @@ -24,43 +25,45 @@ class UserInfoController(
suspend fun getUserInfo(): UserInfoRespons {
val (tilganger, organisasjoner, syfoVirksomheter, refusjoner) = supervisorScope {
val tilganger = async {
altinnService.hentAltinnTilganger().let {
it.tilgangTilOrgNr.map { (tilgang, value) ->
if (tilgang.contains(":")) {
/**
* I frontend mappes tilganger til en record fra tjeneste "id" til et set med orgnr
* dette blir dobbeltarbeid. Endre frontend til å motta map direkte på form:
* {
* "tjenestekode:tjenesteversjon": ["orgnr1", "orgnr2"]
* }
*/
val (tjenestekode, tjenesteversjon) = tilgang.split(":")
UserInfoRespons.Tilgang(
tjenestekode = tjenestekode,
tjenesteversjon = tjenesteversjon,
organisasjoner = value.toList(),
altinnError = it.isError,
)
} else {
/**
* altinn3 ressurser har ingen tjenesteversjon
* her burde vi på sikt ha en bedre måte å skille på
* altinn2 tjeneste tilgang vs altinn3 ressurs tilgang
*/
UserInfoRespons.Tilgang(
tjenestekode = tilgang,
tjenesteversjon = "",
organisasjoner = value.toList(),
altinnError = it.isError,
)
runCatching {
altinnService.hentAltinnTilganger().let {
it.tilgangTilOrgNr.map { (tilgang, value) ->
if (tilgang.contains(":")) {
/**
* I frontend mappes tilganger til en record fra tjeneste "id" til et set med orgnr
* dette blir dobbeltarbeid. Endre frontend til å motta map direkte på form:
* {
* "tjenestekode:tjenesteversjon": ["orgnr1", "orgnr2"]
* }
*/
val (tjenestekode, tjenesteversjon) = tilgang.split(":")
UserInfoRespons.Tilgang(
tjenestekode = tjenestekode,
tjenesteversjon = tjenesteversjon,
organisasjoner = value.toList(),
altinnError = it.isError,
)
} else {
/**
* altinn3 ressurser har ingen tjenesteversjon
* her burde vi på sikt ha en bedre måte å skille på
* altinn2 tjeneste tilgang vs altinn3 ressurs tilgang
*/
UserInfoRespons.Tilgang(
tjenestekode = tilgang,
tjenesteversjon = "",
organisasjoner = value.toList(),
altinnError = it.isError,
)
}
}
}
}
}

val organisasjoner = async {
runCatching {
altinnService.hentOrganisasjoner()
altinnService.hentAltinnTilganger().organisasjonerFlattened
}
}

Expand All @@ -81,17 +84,17 @@ class UserInfoController(
}

return UserInfoRespons(
altinnError = organisasjoner.isFailure || tilganger.any { it.altinnError } || refusjoner.isFailure,
altinnError = organisasjoner.isFailure || (tilganger.isFailure || tilganger.getOrDefault(emptyList()).any { it.altinnError }) || refusjoner.isFailure,
digisyfoError = syfoVirksomheter.isFailure,
organisasjoner = organisasjoner.getOrDefault(emptyList()),
digisyfoOrganisasjoner = syfoVirksomheter.getOrDefault(emptyList()),
refusjoner = refusjoner.getOrDefault(emptyList()),
tilganger = tilganger,
tilganger = tilganger.getOrDefault(emptyList()),
)
}

data class UserInfoData(
val tilganger: List<UserInfoRespons.Tilgang>,
val tilganger: Result<List<UserInfoRespons.Tilgang>>,
val organisasjoner: Result<List<Organisasjon>>,
val digisyfoOrganisasjoner: Result<Collection<VirksomhetOgAntallSykmeldte>>,
val refusjoner: Result<List<RefusjonStatusService.Statusoversikt>>,
Expand All @@ -113,6 +116,51 @@ class UserInfoController(
)
}


@GetMapping("/api/userInfo/v2")
suspend fun getUserInfoV2(): UserInfoV2Respons {
val (tilganger, syfoVirksomheter, refusjoner) = supervisorScope {
val tilganger = async {
runCatching {
altinnService.hentAltinnTilganger()
}
}

val syfoVirksomheter = async {
runCatching {
digisyfoService.hentVirksomheterOgSykmeldte(authenticatedUserHolder.fnr)
}
}

val refusjoner = async {
runCatching {
refusjonStatusService.statusoversikt(authenticatedUserHolder.fnr)
}
}

Triple(tilganger.await(), syfoVirksomheter.await(), refusjoner.await())
}


return UserInfoV2Respons(
altinnError = tilganger.isFailure || tilganger.getOrNull()?.isError ?: false || refusjoner.isFailure,
digisyfoError = syfoVirksomheter.isFailure,
organisasjoner = tilganger.getOrNull()?.hierarki ?: emptyList(),
digisyfoOrganisasjoner = syfoVirksomheter.getOrDefault(emptyList()),
refusjoner = refusjoner.getOrDefault(emptyList()),
tilganger = tilganger.getOrNull()?.tilgangTilOrgNr ?: emptyMap<String, Set<String>>(),
)
}

data class UserInfoV2Respons(
val altinnError: Boolean,
val digisyfoError: Boolean,
val organisasjoner: List<AltinnTilganger.AltinnTilgang>,
val tilganger: Map<String, Collection<String>>,
val digisyfoOrganisasjoner: Collection<VirksomhetOgAntallSykmeldte>,
val refusjoner: List<RefusjonStatusService.Statusoversikt>,
)

sealed interface Tjeneste {
val sort: Sort
val tjenestekode: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ package no.nav.arbeidsgiver.min_side.tiltak

import com.fasterxml.jackson.databind.ObjectMapper
import no.nav.arbeidsgiver.min_side.controller.SecurityMockMvcUtil.Companion.jwtWithPid
import no.nav.arbeidsgiver.min_side.models.Organisasjon
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnService
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnTilgangerResponse
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnTilganger
import no.nav.arbeidsgiver.min_side.services.tiltak.RefusjonStatusKafkaListener
import no.nav.arbeidsgiver.min_side.services.tiltak.RefusjonStatusRepository
import no.nav.arbeidsgiver.min_side.services.tiltak.RefusjonStatusService.Companion.TJENESTEKODE
Expand Down Expand Up @@ -67,23 +66,23 @@ class RefusjonStatusIntegrationTest {
`when`(
altinnService.hentAltinnTilganger()
).thenReturn(
AltinnTilgangerResponse(
AltinnTilganger(
isError = false,
hierarki = listOf(
AltinnTilgangerResponse.AltinnTilgang(
AltinnTilganger.AltinnTilgang(
orgNr = "1",
altinn3Tilganger = setOf(),
altinn2Tilganger = setOf(),
underenheter = listOf(
AltinnTilgangerResponse.AltinnTilgang(
AltinnTilganger.AltinnTilgang(
orgNr = "314",
altinn3Tilganger = setOf(),
altinn2Tilganger = setOf("$TJENESTEKODE:$TJENESTEVERSJON"),
underenheter = listOf(),
name = "Foo & Co",
organizationForm = "BEDR"
),
AltinnTilgangerResponse.AltinnTilgang(
AltinnTilganger.AltinnTilgang(
orgNr = "315",
altinn3Tilganger = setOf(),
altinn2Tilganger = setOf("$TJENESTEKODE:$TJENESTEVERSJON"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import no.nav.arbeidsgiver.min_side.controller.AuthenticatedUserHolder
import no.nav.arbeidsgiver.min_side.controller.SecurityMockMvcUtil.Companion.jwtWithPid
import no.nav.arbeidsgiver.min_side.models.Organisasjon
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnService
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnTilgangerResponse
import no.nav.arbeidsgiver.min_side.services.altinn.AltinnTilganger
import no.nav.arbeidsgiver.min_side.services.digisyfo.DigisyfoService
import no.nav.arbeidsgiver.min_side.services.tiltak.RefusjonStatusService
import org.junit.jupiter.api.Test
import org.mockito.Mockito.anyString
import org.mockito.Mockito.`when`
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
Expand Down Expand Up @@ -51,31 +50,16 @@ class UserInfoControllerTest {

@Test
fun `returnerer organisasjoner og rettigheter for innlogget bruker`() {
`when`(altinnService.hentOrganisasjoner()).thenReturn(
listOf(
Organisasjon(
name = "underenhet",
parentOrganizationNumber = "1",
organizationNumber = "10",
organizationForm = "BEDR"
),
Organisasjon(
name = "overenhet",
organizationNumber = "1",
organizationForm = "AS",
),
)
)
`when`(altinnService.hentAltinnTilganger()).thenReturn(
AltinnTilgangerResponse(
AltinnTilganger(
isError = false,
hierarki = listOf(
AltinnTilgangerResponse.AltinnTilgang(
AltinnTilganger.AltinnTilgang(
orgNr = "1",
altinn3Tilganger = setOf(),
altinn2Tilganger = setOf(),
underenheter = listOf(
AltinnTilgangerResponse.AltinnTilgang(
AltinnTilganger.AltinnTilgang(
orgNr = "10",
altinn3Tilganger = setOf(),
altinn2Tilganger = setOf("3403:1"),
Expand Down Expand Up @@ -194,17 +178,17 @@ class UserInfoControllerTest {
}
],
"organisasjoner": [
{
"Name": "underenhet",
"ParentOrganizationNumber": "1",
"OrganizationNumber": "10",
"OrganizationForm": "BEDR"
},
{
"Name": "overenhet",
"ParentOrganizationNumber": null,
"OrganizationNumber": "1",
"OrganizationForm": "AS"
},
{
"Name": "underenhet",
"ParentOrganizationNumber": "1",
"OrganizationNumber": "10",
"OrganizationForm": "BEDR"
}
],
"tilganger": [
Expand Down

0 comments on commit 7cf956b

Please sign in to comment.