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)