diff --git a/pom.xml b/pom.xml
index 95b0a1d..8adb8ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,12 @@
3.9.1
test
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ 5.3.1
+ test
+
org.testcontainers
testcontainers
diff --git a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/adapter/DataServiceAdapter.kt b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/adapter/DataServiceAdapter.kt
index 0d92e97..afd27ec 100644
--- a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/adapter/DataServiceAdapter.kt
+++ b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/adapter/DataServiceAdapter.kt
@@ -7,7 +7,6 @@ import org.springframework.stereotype.Service
import java.io.BufferedReader
import java.net.HttpURLConnection
import java.net.URI
-import java.net.URL
private const val TEN_MINUTES = 600000
diff --git a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/controller/DataservicesController.kt b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/controller/DataservicesController.kt
index 62040fa..c7d09a7 100644
--- a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/controller/DataservicesController.kt
+++ b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/controller/DataservicesController.kt
@@ -1,5 +1,6 @@
package no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.controller
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.DuplicateIRI
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.rdf.jenaTypeFromAcceptHeader
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.service.DataServiceService
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.service.EndpointPermissions
@@ -54,4 +55,14 @@ open class DataServicesController(
ResponseEntity(HttpStatus.NO_CONTENT)
} else ResponseEntity(HttpStatus.FORBIDDEN)
+ @PostMapping("/duplicates")
+ fun removeDuplicates(
+ @AuthenticationPrincipal jwt: Jwt,
+ @RequestBody duplicates: List
+ ): ResponseEntity =
+ if (endpointPermissions.hasAdminPermission(jwt)) {
+ dataServiceService.removeDuplicates(duplicates)
+ ResponseEntity(HttpStatus.OK)
+ } else ResponseEntity(HttpStatus.FORBIDDEN)
+
}
diff --git a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/harvester/DataServiceHarvester.kt b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/harvester/DataServiceHarvester.kt
index 9b9cc95..7d9f79a 100644
--- a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/harvester/DataServiceHarvester.kt
+++ b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/harvester/DataServiceHarvester.kt
@@ -12,9 +12,6 @@ import org.apache.jena.riot.Lang
import org.slf4j.LoggerFactory
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
-import java.time.ZoneId
-import java.time.ZonedDateTime
-import java.time.format.DateTimeFormatter
import java.util.*
private val LOGGER = LoggerFactory.getLogger(DataServiceHarvester::class.java)
diff --git a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/model/DuplicateIRI.kt b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/model/DuplicateIRI.kt
new file mode 100644
index 0000000..4350a11
--- /dev/null
+++ b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/model/DuplicateIRI.kt
@@ -0,0 +1,7 @@
+package no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model
+
+data class DuplicateIRI(
+ val iriToRetain: String,
+ val iriToRemove: String,
+ val keepRemovedFdkId: Boolean = true
+)
diff --git a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceService.kt b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceService.kt
index dc3baf7..4a72db6 100644
--- a/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceService.kt
+++ b/src/main/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceService.kt
@@ -1,6 +1,7 @@
package no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.service
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.harvester.formatNowWithOsloTimeZone
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.DuplicateIRI
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.FdkIdAndUri
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.HarvestReport
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.rabbit.RabbitMQPublisher
@@ -8,6 +9,7 @@ import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.rdf.*
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.repository.DataServiceRepository
import org.apache.jena.rdf.model.ModelFactory
import org.apache.jena.riot.Lang
+import org.springframework.data.repository.findByIdOrNull
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.server.ResponseStatusException
@@ -65,4 +67,45 @@ class DataServiceService(
}
}
+ fun removeDuplicates(duplicates: List) {
+ val start = formatNowWithOsloTimeZone()
+ val reportAsRemoved: MutableList = mutableListOf()
+
+ duplicates.flatMap { duplicate ->
+ val remove = dataServiceRepository.findByIdOrNull(duplicate.iriToRemove)
+ ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "No data service connected to IRI ${duplicate.iriToRemove}")
+
+ val retain = dataServiceRepository.findByIdOrNull(duplicate.iriToRetain)
+ ?.let { if (it.issued > remove.issued) it.copy(issued = remove.issued) else it } // keep earliest issued
+ ?.let { if (it.modified < remove.modified) it.copy(modified = remove.modified) else it } // keep latest modified
+ ?.let {
+ if (duplicate.keepRemovedFdkId) {
+ if (it.removed) throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Data service with IRI ${it.uri} has already been removed")
+ reportAsRemoved.add(FdkIdAndUri(fdkId = it.fdkId, uri = it.uri))
+ it.copy(fdkId = remove.fdkId)
+ } else {
+ if (remove.removed) throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Data service with IRI ${remove.uri} has already been removed")
+ reportAsRemoved.add(FdkIdAndUri(fdkId = remove.fdkId, uri = remove.uri))
+ it
+ }
+ }
+ ?: remove.copy(uri = duplicate.iriToRetain)
+
+ listOf(remove.copy(removed = true), retain.copy(removed = false))
+ }.run { dataServiceRepository.saveAll(this) }
+
+ if (reportAsRemoved.isNotEmpty()) {
+ rabbitPublisher.send(listOf(
+ HarvestReport(
+ id = "duplicate-delete",
+ url = "https://fellesdatakatalog.digdir.no/duplicates",
+ harvestError = false,
+ startTime = start,
+ endTime = formatNowWithOsloTimeZone(),
+ removedResources = reportAsRemoved
+ )
+ ))
+ }
+ }
+
}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 76e8ac6..503f864 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -6,6 +6,7 @@ logging:
level.org.apache.jena.riot: ERROR
server:
port: 8080
+ error.include-message: always
application:
dataserviceUri: ${FDK_DATASERVICE_HARVESTER_URI:https://dataservices.staging.fellesdatakatalog.digdir.no}/dataservices
catalogUri: ${FDK_DATASERVICE_HARVESTER_URI:https://dataservices.staging.fellesdatakatalog.digdir.no}/catalogs
diff --git a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/contract/DataServicesContract.kt b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/contract/DataServicesContract.kt
index fdc5e4e..0da74af 100644
--- a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/contract/DataServicesContract.kt
+++ b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/contract/DataServicesContract.kt
@@ -1,7 +1,11 @@
package no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.contract
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.DuplicateIRI
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.ApiTestContext
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.DATASERVICE_ID_0
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.DATA_SERVICE_DBO_0
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.DATA_SERVICE_DBO_1
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.TestResponseReader
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.apiGet
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.authorizedRequest
@@ -15,6 +19,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
import kotlin.test.assertTrue
@@ -22,11 +27,13 @@ import kotlin.test.assertTrue
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(
properties = ["spring.profiles.active=contract-test"],
- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
+)
@ContextConfiguration(initializers = [ApiTestContext.Initializer::class])
@Tag("contract")
class DataServicesContract : ApiTestContext() {
private val responseReader = TestResponseReader()
+ private val mapper = jacksonObjectMapper()
@Test
fun findSpecific() {
@@ -61,7 +68,12 @@ class DataServicesContract : ApiTestContext() {
@Test
fun unauthorizedForNoToken() {
- val response = authorizedRequest(port, "/dataservices/$DATASERVICE_ID_0", null, "DELETE")
+ val response = authorizedRequest(
+ port,
+ "/dataservices/$DATASERVICE_ID_0",
+ null,
+ HttpMethod.DELETE
+ )
assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
}
@@ -71,15 +83,19 @@ class DataServicesContract : ApiTestContext() {
port,
"/dataservices/$DATASERVICE_ID_0",
JwtToken(Access.ORG_WRITE).toString(),
- "DELETE"
+ HttpMethod.DELETE
)
assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
}
@Test
fun notFoundWhenIdNotInDB() {
- val response =
- authorizedRequest(port, "/dataservices/123", JwtToken(Access.ROOT).toString(), "DELETE")
+ val response = authorizedRequest(
+ port,
+ "/dataservices/123",
+ JwtToken(Access.ROOT).toString(),
+ HttpMethod.DELETE
+ )
assertEquals(HttpStatus.NOT_FOUND.value(), response["status"])
}
@@ -89,10 +105,67 @@ class DataServicesContract : ApiTestContext() {
port,
"/dataservices/$DATASERVICE_ID_0",
JwtToken(Access.ROOT).toString(),
- "DELETE"
+ HttpMethod.DELETE
)
assertEquals(HttpStatus.NO_CONTENT.value(), response["status"])
}
}
+ @Nested
+ internal inner class RemoveDuplicates {
+
+ @Test
+ fun unauthorizedForNoToken() {
+ val body = listOf(DuplicateIRI(iriToRemove = DATA_SERVICE_DBO_0.uri, iriToRetain = DATA_SERVICE_DBO_1.uri))
+ val response = authorizedRequest(
+ port,
+ "/dataservices/duplicates",
+ null,
+ HttpMethod.POST,
+ mapper.writeValueAsString(body)
+ )
+ assertEquals(HttpStatus.UNAUTHORIZED.value(), response["status"])
+ }
+
+ @Test
+ fun forbiddenWithNonSysAdminRole() {
+ val body = listOf(DuplicateIRI(iriToRemove = DATA_SERVICE_DBO_0.uri, iriToRetain = DATA_SERVICE_DBO_1.uri))
+ val response = authorizedRequest(
+ port,
+ "/dataservices/duplicates",
+ JwtToken(Access.ORG_WRITE).toString(),
+ HttpMethod.POST,
+ mapper.writeValueAsString(body)
+ )
+ assertEquals(HttpStatus.FORBIDDEN.value(), response["status"])
+ }
+
+ @Test
+ fun badRequestWhenRemoveIRINotInDB() {
+ val body = listOf(DuplicateIRI(iriToRemove = "https://123.no", iriToRetain = DATA_SERVICE_DBO_1.uri))
+ val response =
+ authorizedRequest(
+ port,
+ "/dataservices/duplicates",
+ JwtToken(Access.ROOT).toString(),
+ HttpMethod.POST,
+ mapper.writeValueAsString(body)
+ )
+ assertEquals(HttpStatus.BAD_REQUEST.value(), response["status"])
+ }
+
+ @Test
+ fun okWithSysAdminRole() {
+ val body = listOf(DuplicateIRI(iriToRemove = DATA_SERVICE_DBO_0.uri, iriToRetain = DATA_SERVICE_DBO_1.uri))
+ val response = authorizedRequest(
+ port,
+ "/dataservices/duplicates",
+ JwtToken(Access.ROOT).toString(),
+ HttpMethod.POST,
+ mapper.writeValueAsString(body)
+ )
+ assertEquals(HttpStatus.OK.value(), response["status"])
+ }
+ }
+
}
diff --git a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceServiceTest.kt b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceServiceTest.kt
index 0642fe0..b7b6975 100644
--- a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceServiceTest.kt
+++ b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/service/DataServiceServiceTest.kt
@@ -1,6 +1,7 @@
package no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.service
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.DataServiceMeta
+import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.DuplicateIRI
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.FdkIdAndUri
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.model.HarvestReport
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.rabbit.RabbitMQPublisher
@@ -12,12 +13,14 @@ import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
+import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.springframework.web.server.ResponseStatusException
+import java.util.*
import kotlin.test.assertNull
import kotlin.test.assertTrue
@@ -186,4 +189,152 @@ class DatasetServiceTest {
}
+ @Nested
+ internal inner class RemoveDuplicates {
+
+ @Test
+ fun throwsExceptionWhenRemoveIRINotFoundInDB() {
+ whenever(repository.findById("https://123.no"))
+ .thenReturn(Optional.empty())
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_1))
+
+ val duplicateIRI = DuplicateIRI(
+ iriToRemove = "https://123.no",
+ iriToRetain = DATA_SERVICE_DBO_1.uri
+ )
+ assertThrows { dataServiceService.removeDuplicates(listOf(duplicateIRI)) }
+ }
+
+ @Test
+ fun createsNewMetaWhenRetainIRINotFoundInDB() {
+ whenever(repository.findById(DATA_SERVICE_DBO_0.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_0))
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.empty())
+
+ val duplicateIRI = DuplicateIRI(
+ iriToRemove = DATA_SERVICE_DBO_0.uri,
+ iriToRetain = DATA_SERVICE_DBO_1.uri
+ )
+ dataServiceService.removeDuplicates(listOf(duplicateIRI))
+
+ argumentCaptor>().apply {
+ verify(repository, times(1)).saveAll(capture())
+ assertEquals(listOf(DATA_SERVICE_DBO_0.copy(removed = true), DATA_SERVICE_DBO_0.copy(uri = DATA_SERVICE_DBO_1.uri)), firstValue)
+ }
+
+ verify(publisher, times(0)).send(any())
+ }
+
+ @Test
+ fun sendsRabbitReportWithRetainFdkIdWhenKeepingRemoveFdkId() {
+ whenever(repository.findById(DATA_SERVICE_DBO_0.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_0))
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_1))
+
+ val duplicateIRI = DuplicateIRI(
+ iriToRemove = DATA_SERVICE_DBO_0.uri,
+ iriToRetain = DATA_SERVICE_DBO_1.uri
+ )
+ dataServiceService.removeDuplicates(listOf(duplicateIRI))
+
+ argumentCaptor>().apply {
+ verify(repository, times(1)).saveAll(capture())
+ assertEquals(listOf(
+ DATA_SERVICE_DBO_0.copy(removed = true),
+ DATA_SERVICE_DBO_0.copy(uri = DATA_SERVICE_DBO_1.uri, isPartOf = DATA_SERVICE_DBO_1.isPartOf)
+ ), firstValue)
+ }
+
+ val expectedReport = HarvestReport(
+ id = "duplicate-delete",
+ url = "https://fellesdatakatalog.digdir.no/duplicates",
+ harvestError = false,
+ startTime = "startTime",
+ endTime = "endTime",
+ removedResources = listOf(FdkIdAndUri(DATA_SERVICE_DBO_1.fdkId, DATA_SERVICE_DBO_1.uri))
+ )
+ argumentCaptor>().apply {
+ verify(publisher, times(1)).send(capture())
+
+ assertEquals(
+ listOf(expectedReport.copy(
+ startTime = firstValue.first().startTime,
+ endTime = firstValue.first().endTime
+ )),
+ firstValue
+ )
+ }
+ }
+
+ @Test
+ fun sendsRabbitReportWithRemoveFdkIdWhenNotKeepingRemoveFdkId() {
+ whenever(repository.findById(DATA_SERVICE_DBO_0.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_0))
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_1))
+
+ val duplicateIRI = DuplicateIRI(
+ iriToRemove = DATA_SERVICE_DBO_1.uri,
+ iriToRetain = DATA_SERVICE_DBO_0.uri,
+ keepRemovedFdkId = false
+ )
+ dataServiceService.removeDuplicates(listOf(duplicateIRI))
+
+ argumentCaptor>().apply {
+ verify(repository, times(1)).saveAll(capture())
+ assertEquals(listOf(
+ DATA_SERVICE_DBO_1.copy(removed = true),
+ DATA_SERVICE_DBO_0
+ ), firstValue)
+ }
+
+ val expectedReport = HarvestReport(
+ id = "duplicate-delete",
+ url = "https://fellesdatakatalog.digdir.no/duplicates",
+ harvestError = false,
+ startTime = "startTime",
+ endTime = "endTime",
+ removedResources = listOf(FdkIdAndUri(DATA_SERVICE_DBO_1.fdkId, DATA_SERVICE_DBO_1.uri))
+ )
+ argumentCaptor>().apply {
+ verify(publisher, times(1)).send(capture())
+
+ assertEquals(
+ listOf(expectedReport.copy(
+ startTime = firstValue.first().startTime,
+ endTime = firstValue.first().endTime
+ )),
+ firstValue
+ )
+ }
+ }
+
+ @Test
+ fun throwsExceptionWhenTryingToReportAlreadyRemovedAsRemoved() {
+ whenever(repository.findById(DATA_SERVICE_DBO_0.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_0.copy(removed = true)))
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_1))
+
+ val duplicateIRI = DuplicateIRI(
+ iriToRemove = DATA_SERVICE_DBO_0.uri,
+ iriToRetain = DATA_SERVICE_DBO_1.uri,
+ keepRemovedFdkId = false
+ )
+
+ assertThrows { dataServiceService.removeDuplicates(listOf(duplicateIRI)) }
+
+ whenever(repository.findById(DATA_SERVICE_DBO_0.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_0))
+ whenever(repository.findById(DATA_SERVICE_DBO_1.uri))
+ .thenReturn(Optional.of(DATA_SERVICE_DBO_1.copy(removed = true)))
+
+ assertThrows { dataServiceService.removeDuplicates(listOf(duplicateIRI.copy(keepRemovedFdkId = true))) }
+ }
+
+ }
+
}
diff --git a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/utils/TestUtils.kt b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/utils/TestUtils.kt
index cbb94df..5b9bbfd 100644
--- a/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/utils/TestUtils.kt
+++ b/src/test/kotlin/no/digdir/informasjonsforvaltning/fdk_dataservice_harvester/utils/TestUtils.kt
@@ -7,82 +7,98 @@ import com.mongodb.client.MongoClients
import no.digdir.informasjonsforvaltning.fdk_dataservice_harvester.utils.ApiTestContext.Companion.mongoContainer
import org.bson.codecs.configuration.CodecRegistries
import org.bson.codecs.pojo.PojoCodecProvider
-import org.slf4j.LoggerFactory
+import org.springframework.http.HttpEntity
+import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpMethod
import java.io.BufferedReader
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.net.HttpURLConnection
import java.net.URI
-private val logger = LoggerFactory.getLogger(ApiTestContext::class.java)
-
-fun apiGet(port: Int, endpoint: String, acceptHeader: String?): Map {
+fun apiGet(port: Int, endpoint: String, acceptHeader: String?): Map {
return try {
val connection = URI("http://localhost:$port$endpoint").toURL().openConnection() as HttpURLConnection
- if(acceptHeader != null) connection.setRequestProperty("Accept", acceptHeader)
+ if (acceptHeader != null) connection.setRequestProperty("Accept", acceptHeader)
connection.connect()
- if(isOK(connection.responseCode)) {
+ if (isOK(connection.responseCode)) {
val responseBody = connection.inputStream.bufferedReader().use(BufferedReader::readText)
mapOf(
- "body" to responseBody,
+ "body" to responseBody,
"header" to connection.headerFields.toString(),
- "status" to connection.responseCode)
+ "status" to connection.responseCode
+ )
} else {
mapOf(
"status" to connection.responseCode,
"header" to " ",
- "body" to " "
+ "body" to " "
)
}
} catch (e: Exception) {
mapOf(
"status" to e.toString(),
"header" to " ",
- "body" to " "
+ "body" to " "
)
}
}
-fun authorizedRequest(port: Int, endpoint: String, token: String?, method: String = "POST", headers: Map = emptyMap()): Map {
+fun authorizedRequest(
+ port: Int,
+ endpoint: String,
+ token: String?,
+ method: HttpMethod = HttpMethod.POST,
+ body: String? = null,
+ headers: Map = emptyMap()
+): Map {
+ val request = RestTemplate()
+ request.requestFactory = HttpComponentsClientHttpRequestFactory()
+ val url = "http://localhost:$port$endpoint"
+ val httpHeaders = HttpHeaders()
+ token?.let { httpHeaders.setBearerAuth(it) }
+ httpHeaders.contentType = MediaType.APPLICATION_JSON
+ headers.forEach { httpHeaders.set(it.key, it.value) }
+ val entity: HttpEntity = HttpEntity(body, httpHeaders)
return try {
- val connection = URI("http://localhost:$port$endpoint").toURL().openConnection() as HttpURLConnection
- headers.forEach { (key, value) -> connection.setRequestProperty(key, value) }
- if(!token.isNullOrEmpty()) connection.setRequestProperty("Authorization", "Bearer $token")
-
- connection.requestMethod = method
- connection.connect()
-
- 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)
- } else {
- mapOf(
- "status" to connection.responseCode,
- "header" to " ",
- "body" to " "
- )
- }
+ val response = request.exchange(url, method, entity, String::class.java)
+ mapOf(
+ "body" to response.body,
+ "header" to response.headers.toString(),
+ "status" to response.statusCode.value()
+ )
+ } 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 " "
+ "body" to " "
)
}
}
private fun isOK(response: Int?): Boolean =
- if(response == null) false
+ if (response == null) false
else HttpStatus.resolve(response)?.is2xxSuccessful == true
fun populateDB() {
- val connectionString = ConnectionString("mongodb://${MONGO_USER}:${MONGO_PASSWORD}@localhost:${mongoContainer.getMappedPort(MONGO_PORT)}/dataServiceHarvester?authSource=admin&authMechanism=SCRAM-SHA-1")
- val pojoCodecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()))
+ val connectionString =
+ ConnectionString("mongodb://${MONGO_USER}:${MONGO_PASSWORD}@localhost:${mongoContainer.getMappedPort(MONGO_PORT)}/dataServiceHarvester?authSource=admin&authMechanism=SCRAM-SHA-1")
+ val pojoCodecRegistry = CodecRegistries.fromRegistries(
+ MongoClientSettings.getDefaultCodecRegistry(),
+ CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
+ )
val client: MongoClient = MongoClients.create(connectionString)
val mongoDatabase = client.getDatabase("dataServiceHarvester").withCodecRegistry(pojoCodecRegistry)