diff --git a/pom.xml b/pom.xml
index e0edad8..a94ef10 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,17 @@
com.fasterxml.jackson.module
jackson-module-kotlin
+
+
+ jakarta.json
+ jakarta.json-api
+ 2.1.3
+
+
+ org.eclipse.parsson
+ jakarta.json
+ 1.1.5
+
diff --git a/src/main/kotlin/no/digdir/service_catalog/controller/PublicServiceController.kt b/src/main/kotlin/no/digdir/service_catalog/controller/PublicServiceController.kt
index c65538d..d9e6309 100644
--- a/src/main/kotlin/no/digdir/service_catalog/controller/PublicServiceController.kt
+++ b/src/main/kotlin/no/digdir/service_catalog/controller/PublicServiceController.kt
@@ -1,5 +1,6 @@
package no.digdir.service_catalog.controller
+import no.digdir.service_catalog.model.JsonPatchOperation
import no.digdir.service_catalog.model.PublicService
import no.digdir.service_catalog.security.EndpointPermissions
import no.digdir.service_catalog.service.PublicServiceService
@@ -11,7 +12,9 @@ import org.springframework.security.oauth2.jwt.Jwt
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
@Controller
@@ -39,4 +42,19 @@ class PublicServiceController(private val publicServiceService: PublicServiceSer
} else {
ResponseEntity(HttpStatus.FORBIDDEN)
}
+
+ @PatchMapping(value = ["/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
+ fun patchCodeList(
+ @AuthenticationPrincipal jwt: Jwt,
+ @PathVariable catalogId: String,
+ @PathVariable id: String,
+ @RequestBody patchOperations: List
+ ): ResponseEntity =
+ if (endpointPermissions.hasOrgWritePermission(jwt, catalogId)) {
+ publicServiceService.patchPublicService(id, catalogId, patchOperations)
+ ?.let { ResponseEntity(it, HttpStatus.OK) }
+ ?: ResponseEntity(HttpStatus.NOT_FOUND)
+ } else {
+ ResponseEntity(HttpStatus.FORBIDDEN)
+ }
}
diff --git a/src/main/kotlin/no/digdir/service_catalog/model/JsonPatchOperation.kt b/src/main/kotlin/no/digdir/service_catalog/model/JsonPatchOperation.kt
new file mode 100644
index 0000000..d4d5420
--- /dev/null
+++ b/src/main/kotlin/no/digdir/service_catalog/model/JsonPatchOperation.kt
@@ -0,0 +1,23 @@
+package no.digdir.service_catalog.model
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties
+import com.fasterxml.jackson.annotation.JsonValue
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+data class JsonPatchOperation (
+ val op: OpEnum,
+ val path: String,
+ val value: Any? = null,
+ val from: String? = null
+)
+
+enum class OpEnum(val value: String) {
+ ADD("add"),
+ REMOVE("remove"),
+ REPLACE("replace"),
+ MOVE("move"),
+ COPY("copy");
+
+ @JsonValue
+ fun jsonValue(): String = value
+}
diff --git a/src/main/kotlin/no/digdir/service_catalog/service/JsonPatchUtils.kt b/src/main/kotlin/no/digdir/service_catalog/service/JsonPatchUtils.kt
new file mode 100644
index 0000000..37289c0
--- /dev/null
+++ b/src/main/kotlin/no/digdir/service_catalog/service/JsonPatchUtils.kt
@@ -0,0 +1,46 @@
+package no.digdir.service_catalog.service
+
+import com.fasterxml.jackson.core.JsonProcessingException
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.fasterxml.jackson.module.kotlin.readValue
+import jakarta.json.Json
+import jakarta.json.JsonException
+import no.digdir.service_catalog.model.JsonPatchOperation
+import org.springframework.http.HttpStatus
+import org.springframework.web.server.ResponseStatusException
+import java.io.StringReader
+
+inline fun patchOriginal(original: T, operations: List): T {
+ validateOperations(operations)
+ try {
+ return applyPatch(original, operations)
+ } catch (ex: Exception) {
+ when (ex) {
+ is JsonException -> throw ResponseStatusException(HttpStatus.BAD_REQUEST, ex.message)
+ is JsonProcessingException -> throw ResponseStatusException(HttpStatus.BAD_REQUEST, ex.message)
+ is IllegalArgumentException -> throw ResponseStatusException(HttpStatus.BAD_REQUEST, ex.message)
+ else -> throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, ex.message)
+ }
+ }
+}
+
+inline fun applyPatch(originalObject: T, operations: List): T {
+ if (operations.isNotEmpty()) {
+ with(jacksonObjectMapper()) {
+ val changes = Json.createReader(StringReader(writeValueAsString(operations))).readArray()
+ val original = Json.createReader(StringReader(writeValueAsString(originalObject))).readObject()
+
+ return Json.createPatch(changes).apply(original)
+ .let { readValue(it.toString()) }
+ }
+ }
+ return originalObject
+}
+
+fun validateOperations(operations: List) {
+ val invalidPaths = listOf("/id", "/catalogId")
+ if (operations.any { it.path in invalidPaths }) {
+ throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Patch of paths $invalidPaths is not permitted")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/no/digdir/service_catalog/service/PublicServiceService.kt b/src/main/kotlin/no/digdir/service_catalog/service/PublicServiceService.kt
index 08886f0..5204310 100644
--- a/src/main/kotlin/no/digdir/service_catalog/service/PublicServiceService.kt
+++ b/src/main/kotlin/no/digdir/service_catalog/service/PublicServiceService.kt
@@ -1,12 +1,16 @@
package no.digdir.service_catalog.service
+import no.digdir.service_catalog.model.JsonPatchOperation
import no.digdir.service_catalog.model.PublicService
import no.digdir.service_catalog.mongodb.PublicServiceRepository
+import org.slf4j.LoggerFactory
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
@Service
class PublicServiceService(private val publicServiceRepository: PublicServiceRepository) {
+ private val logger = LoggerFactory.getLogger(PublicServiceService::class.java)
+
fun findPublicServicesByCatalogId(catalogId: String) =
publicServiceRepository.getByCatalogId(catalogId)
@@ -14,4 +18,14 @@ class PublicServiceService(private val publicServiceRepository: PublicServiceRep
publicServiceRepository
.findByIdOrNull(id)
?.takeIf { it.catalogId == catalogId }
+
+ fun patchPublicService(id: String, catalogId: String, operations: List): PublicService? =
+ try {
+ findPublicServiceById(id, catalogId)
+ ?.let { patchOriginal(it, operations)}
+ ?.let { publicServiceRepository.save(it) }
+ } catch (ex: Exception) {
+ logger.error("Failed to update code-list with id $id in catalog $catalogId", ex)
+ throw ex
+ }
}
diff --git a/src/test/kotlin/no/digdir/service_catalog/integration/GetServices.kt b/src/test/kotlin/no/digdir/service_catalog/integration/GetServices.kt
index b7f516b..7c2a0f5 100644
--- a/src/test/kotlin/no/digdir/service_catalog/integration/GetServices.kt
+++ b/src/test/kotlin/no/digdir/service_catalog/integration/GetServices.kt
@@ -6,7 +6,6 @@ import no.digdir.service_catalog.model.Service
import no.digdir.service_catalog.utils.ApiTestContext
import no.digdir.service_catalog.utils.SERVICES
import no.digdir.service_catalog.utils.apiAuthorizedRequest
-import no.digdir.service_catalog.utils.apiGet
import no.digdir.service_catalog.utils.jwt.Access
import no.digdir.service_catalog.utils.jwt.JwtToken
import org.junit.jupiter.api.Assertions
@@ -14,6 +13,7 @@ import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.test.context.ContextConfiguration
@@ -28,7 +28,7 @@ class GetServices: ApiTestContext() {
@Test
fun `able to get all services`() {
- val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, JwtToken(Access.ORG_READ).toString(), "GET")
+ val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, JwtToken(Access.ORG_READ).toString(), HttpMethod.GET)
Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
val result: List = mapper.readValue(response["body"] as String)
@@ -37,13 +37,13 @@ class GetServices: ApiTestContext() {
@Test
fun `unauthorized when missing token`() {
- val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, null, "GET")
+ val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, null, HttpMethod.GET)
Assertions.assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
}
@Test
fun `forbidden when authorized for other catalog`() {
- val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, JwtToken(Access.WRONG_ORG_READ).toString(), "GET")
+ val response = apiAuthorizedRequest("/catalogs/910244132/services", port, null, JwtToken(Access.WRONG_ORG_READ).toString(), HttpMethod.GET)
Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
}
}
diff --git a/src/test/kotlin/no/digdir/service_catalog/integration/PublicServices.kt b/src/test/kotlin/no/digdir/service_catalog/integration/PublicServices.kt
index 8613362..5ea9c63 100644
--- a/src/test/kotlin/no/digdir/service_catalog/integration/PublicServices.kt
+++ b/src/test/kotlin/no/digdir/service_catalog/integration/PublicServices.kt
@@ -2,18 +2,25 @@ package no.digdir.service_catalog.integration
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import no.digdir.service_catalog.model.JsonPatchOperation
+import no.digdir.service_catalog.model.LocalizedStrings
+import no.digdir.service_catalog.model.OpEnum
import no.digdir.service_catalog.model.PublicService
import no.digdir.service_catalog.utils.ApiTestContext
import no.digdir.service_catalog.utils.PUBLIC_SERVICES
+import no.digdir.service_catalog.utils.PUBLIC_SERVICE_0
import no.digdir.service_catalog.utils.PUBLIC_SERVICE_1
+import no.digdir.service_catalog.utils.PUBLIC_SERVICE_2
import no.digdir.service_catalog.utils.apiAuthorizedRequest
import no.digdir.service_catalog.utils.jwt.Access
import no.digdir.service_catalog.utils.jwt.JwtToken
import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.test.context.ContextConfiguration
@@ -26,63 +33,275 @@ import org.springframework.test.context.ContextConfiguration
class PublicServices: ApiTestContext() {
private val mapper = jacksonObjectMapper()
- @Test
- fun `able to get all public services`() {
- val response = apiAuthorizedRequest(
- "/catalogs/910244132/public-services",
- port,
- null,
- JwtToken(Access.ORG_READ).toString(),
- "GET")
- Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
-
- val result: List = mapper.readValue(response["body"] as String)
- Assertions.assertEquals(PUBLIC_SERVICES, result)
- }
+ @Nested
+ internal inner class GetPublicServices {
+ @Test
+ fun `able to get all public services`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services",
+ port,
+ null,
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.GET)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
- @Test
- fun `unauthorized when missing token`() {
- val response = apiAuthorizedRequest(
- "/catalogs/910244132/public-services",
- port,
- null,
- null,
- "GET")
- Assertions.assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
- }
+ val result: List = mapper.readValue(response["body"] as String)
+ Assertions.assertEquals(PUBLIC_SERVICES, result)
+ }
- @Test
- fun `forbidden when authorized for other catalog`() {
- val response = apiAuthorizedRequest(
- "/catalogs/910244132/public-services",
- port,
- null,
- JwtToken(Access.WRONG_ORG_READ).toString(),
- "GET")
- Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ @Test
+ fun `unauthorized when missing token`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services",
+ port,
+ null,
+ null,
+ HttpMethod.GET)
+ Assertions.assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
+ }
+
+ @Test
+ fun `forbidden when authorized for other catalog`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services",
+ port,
+ null,
+ JwtToken(Access.WRONG_ORG_READ).toString(),
+ HttpMethod.GET)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
}
- @Test
- fun `able to get public service by id`() {
- val response = apiAuthorizedRequest(
- "/catalogs/910244132/public-services/1",
- port,
- null,
- JwtToken(Access.ORG_READ).toString(),
- "GET")
- Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
- val result: PublicService = mapper.readValue(response["body"] as String)
- Assertions.assertEquals(PUBLIC_SERVICE_1, result)
+ @Nested
+ internal inner class GetPublicService {
+ @Test
+ fun `able to get public service by id`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ null,
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.GET)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ Assertions.assertEquals(PUBLIC_SERVICE_1, result)
+ }
+
+ @Test
+ fun `receive not found when public service is not found`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1000",
+ port,
+ null,
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.GET)
+ Assertions.assertEquals(HttpStatus.NOT_FOUND.value(), response["status"])
+ }
}
- @Test
- fun `receive not found when public service is not found`() {
- val response = apiAuthorizedRequest(
- "/catalogs/910244132/public-services/1000",
- port,
- null,
- JwtToken(Access.ORG_READ).toString(),
- "GET")
- Assertions.assertEquals(HttpStatus.NOT_FOUND.value(), response["status"])
+ @Nested
+ internal inner class PatchPublicService {
+ @Test
+ fun `unauthorized when missing token`() {
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services",
+ port,
+ null,
+ null,
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
+ }
+
+ @Test
+ fun `forbidden when authorized for other catalog`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.REPLACE,
+ path = "/title/nb",
+ value = "oppdater tittel"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.WRONG_ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `forbidden to replace public service nb tittle when authenticated as read user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.REPLACE,
+ path = "/title/nb",
+ value = "oppdater tittel"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `able to replace public service nb tittle when authenticated as write user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.REPLACE,
+ path = "/title/nb",
+ value = "oppdater tittel"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.PATCH)
+
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ val expected = PUBLIC_SERVICE_1.copy(title = PUBLIC_SERVICE_1.title!!.copy(nb = "oppdater tittel"))
+
+ Assertions.assertEquals(expected, result)
+ }
+
+ @Test
+ fun `forbidden to remove public service title when authenticated as read user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.REMOVE,
+ path = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `able to remove public service title when authenticated as write user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.REMOVE,
+ path = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ val expected = PUBLIC_SERVICE_1.copy(title = PUBLIC_SERVICE_1.title!!.copy(nb = null))
+
+ Assertions.assertEquals(expected, result)
+ }
+
+ @Test
+ fun `forbidden to add public service description when authenticated as read user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.ADD,
+ path = "/description",
+ value = LocalizedStrings("added nb description", null, null)))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/2",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `able to add public service description when authenticated as write user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.ADD,
+ path = "/description",
+ value = LocalizedStrings("added nb description", null, null)))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/2",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ val expected = PUBLIC_SERVICE_2
+ .copy(description = LocalizedStrings(nb = "added nb description", null, null))
+
+ Assertions.assertEquals(expected, result)
+ }
+
+ @Test
+ fun `forbidden to move public service nb title to nn when authenticated as read user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.MOVE,
+ path = "/title/nn",
+ from = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/0",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `able to move public service nb title to nn when authenticated as write user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.MOVE,
+ path = "/title/nn",
+ from = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/0",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ val expected = PUBLIC_SERVICE_0
+ .copy(title = PUBLIC_SERVICE_0.title!!.copy(null, nn = "NB Tittel 0"))
+
+ Assertions.assertEquals(expected, result)
+ }
+
+ @Test
+ fun `forbidden to copy public service nb description to nn when authenticated as read user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.COPY,
+ path = "/title/nn",
+ from = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_READ).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun `able to copy public service nb description to nn when authenticated as write user`() {
+ val operations = listOf(JsonPatchOperation(
+ op = OpEnum.COPY,
+ path = "/title/nn",
+ from = "/title/nb"))
+ val response = apiAuthorizedRequest(
+ "/catalogs/910244132/public-services/1",
+ port,
+ mapper.writeValueAsString(operations),
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.PATCH)
+ Assertions.assertEquals(HttpStatus.OK.value(), response["status"])
+
+ val result: PublicService = mapper.readValue(response["body"] as String)
+ val expected = PUBLIC_SERVICE_1
+ .copy(title = PUBLIC_SERVICE_1.title!!.copy(nb = "NB Tittel 1", nn = "NB Tittel 1"))
+
+ Assertions.assertEquals(expected, result)
+ }
}
}
diff --git a/src/test/kotlin/no/digdir/service_catalog/utils/TestData.kt b/src/test/kotlin/no/digdir/service_catalog/utils/TestData.kt
index f0446e8..165aa86 100644
--- a/src/test/kotlin/no/digdir/service_catalog/utils/TestData.kt
+++ b/src/test/kotlin/no/digdir/service_catalog/utils/TestData.kt
@@ -17,16 +17,20 @@ val MONGO_ENV_VALUES: Map = ImmutableMap.of(
val SERVICE_0 = Service("0", "title 0")
val SERVICE_1 = Service("1", "title 1")
+val SERVICE_2 = Service("2", "title 2")
-val SERVICES = listOf(SERVICE_0, SERVICE_1)
+val SERVICES = listOf(SERVICE_0, SERVICE_1, SERVICE_2)
val PUBLIC_SERVICE_0 =
PublicService("0", "910244132",
- title = LocalizedStrings("Tittel 0", "Tittel 0", "Tittel 0"),
+ title = LocalizedStrings("NB Tittel 0", "NN Tittel 0", "EN Tittel 0"),
description = LocalizedStrings("Beskrivelse 0", "Beskriving 0", "Description 0"))
val PUBLIC_SERVICE_1 =
PublicService("1", "910244132",
- title = LocalizedStrings("Tittel 1", "Tittel 1", "Tittel 1"),
+ title = LocalizedStrings("NB Tittel 1", "NN Tittel 1", "EN Tittel 1"),
description = LocalizedStrings("Beskrivelse 1", "Beskriving 1", "Description 1"))
+val PUBLIC_SERVICE_2 =
+ PublicService("2", "910244132",
+ title = LocalizedStrings("NB Tittel 2", "NN Tittel 2", "EN Tittel 2"), null)
-val PUBLIC_SERVICES = listOf(PUBLIC_SERVICE_0, PUBLIC_SERVICE_1)
+val PUBLIC_SERVICES = listOf(PUBLIC_SERVICE_0, PUBLIC_SERVICE_1, PUBLIC_SERVICE_2)
diff --git a/src/test/kotlin/no/digdir/service_catalog/utils/TestUtils.kt b/src/test/kotlin/no/digdir/service_catalog/utils/TestUtils.kt
index a26bc03..8808b47 100644
--- a/src/test/kotlin/no/digdir/service_catalog/utils/TestUtils.kt
+++ b/src/test/kotlin/no/digdir/service_catalog/utils/TestUtils.kt
@@ -1,6 +1,13 @@
package no.digdir.service_catalog.utils
+import org.springframework.http.HttpEntity
+import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
+import org.springframework.web.client.HttpClientErrorException
+import org.springframework.web.client.RestTemplate
import java.io.BufferedReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
@@ -16,21 +23,21 @@ fun apiGet(port: Int, endpoint: String, acceptHeader: String?): Map
if(isOK(connection.responseCode)) {
val responseBody = connection.inputStream.bufferedReader().use(BufferedReader::readText)
mapOf(
- "body" to responseBody,
- "header" to connection.headerFields.toString(),
- "status" to connection.responseCode)
+ "body" to responseBody,
+ "header" to connection.headerFields.toString(),
+ "status" to connection.responseCode)
} else {
mapOf(
- "status" to connection.responseCode,
- "header" to " ",
- "body" to " "
+ "status" to connection.responseCode,
+ "header" to " ",
+ "body" to " "
)
}
} catch (e: Exception) {
mapOf(
- "status" to e.toString(),
- "header" to " ",
- "body" to " "
+ "status" to e.toString(),
+ "header" to " ",
+ "body" to " "
)
}}
@@ -38,44 +45,40 @@ private fun isOK(response: Int?): Boolean =
if(response == null) false
else HttpStatus.resolve(response)?.is2xxSuccessful == true
-fun apiAuthorizedRequest(path: String, port: Int, body: String?, token: String?, method: String): Map {
- val connection = URL("http://localhost:$port$path").openConnection() as HttpURLConnection
- connection.requestMethod = method
- connection.setRequestProperty("Content-type", "application/json")
- connection.setRequestProperty("Accept", "application/json")
+fun apiAuthorizedRequest(
+ path: String, port: Int, body: String?, token: String?, httpMethod: HttpMethod,
+ accept: MediaType = MediaType.APPLICATION_JSON
+): Map {
- if(!token.isNullOrEmpty()) {
- connection.setRequestProperty("Authorization", "Bearer $token")
- }
- return try {
- connection.doOutput = true
- connection.connect()
+ val request = RestTemplate()
+ request.requestFactory = HttpComponentsClientHttpRequestFactory()
+ val url = "http://localhost:$port$path"
+ val headers = HttpHeaders()
+ headers.accept = listOf(accept)
+ token?.let { headers.setBearerAuth(it) }
+ headers.contentType = MediaType.APPLICATION_JSON
+ val entity: HttpEntity = HttpEntity(body, headers)
- if(body != null) {
- val writer = OutputStreamWriter(connection.outputStream)
- writer.write(body)
- writer.close()
- }
+ return try {
+ val response = request.exchange(url, httpMethod, entity, String::class.java)
+ mapOf(
+ "body" to response.body,
+ "header" to response.headers,
+ "status" to response.statusCode.value()
+ )
- if(isOK(connection.responseCode)){
- mapOf(
- "body" to connection.inputStream.bufferedReader().use(BufferedReader :: readText),
- "header" to connection.headerFields.toString(),
- "status" to connection.responseCode
- )
- } else {
- mapOf(
- "status" to connection.responseCode,
- "header" to " ",
- "body" to " "
- )
- }
+ } catch (e: HttpClientErrorException) {
+ mapOf(
+ "status" to e.statusCode.value(),
+ "header" to " ",
+ "body" to e.toString()
+ )
} catch (e: Exception) {
mapOf(
- "status" to e.toString(),
- "header" to " ",
- "body" to " "
+ "status" to e.toString(),
+ "header" to " ",
+ "body" to " "
)
}
}