From 8da0cfd8a326053d0f475d2bb4c4a54cc6963e8b Mon Sep 17 00:00:00 2001 From: Santeri Korri Date: Wed, 10 Jan 2024 13:14:45 +0200 Subject: [PATCH] =?UTF-8?q?Lis=C3=A4tty=20kirjastoon=20l=C3=A4hetyksen=20v?= =?UTF-8?q?astaanottajien=20haku?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oph/viestinvalitys/IntegraatioTesti.scala | 8 +-- .../ViestinvalitysClientTest.java | 41 +++++++++++++- .../ViestinvalitysClient.java | 7 ++- .../ViestinvalitysClient.scala | 54 +++++++++++++++++-- .../model/VastaanottajaResponse.java | 23 ++++++++ .../resource/LahetysResponses.scala | 16 ++++-- .../resource/LahetysResource.scala | 12 +++-- 7 files changed, 143 insertions(+), 18 deletions(-) create mode 100644 lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/model/VastaanottajaResponse.java diff --git a/integraatio/src/test/scala/fi/oph/viestinvalitys/IntegraatioTesti.scala b/integraatio/src/test/scala/fi/oph/viestinvalitys/IntegraatioTesti.scala index 7c76a9bc..898cd096 100644 --- a/integraatio/src/test/scala/fi/oph/viestinvalitys/IntegraatioTesti.scala +++ b/integraatio/src/test/scala/fi/oph/viestinvalitys/IntegraatioTesti.scala @@ -280,7 +280,7 @@ class IntegraatioTesti extends BaseIntegraatioTesti { // tulos vastaa luotua viestiä val getVastaanottajatResponse = objectMapper.readValue(getResult.getResponse.getContentAsString(StandardCharset.UTF_8), classOf[VastaanottajatSuccessResponse]) - Assertions.assertEquals(viesti.vastaanottajat.get.asScala.map(v => v.getSahkopostiOsoite.get), getVastaanottajatResponse.vastaanottajat.asScala.map(v => v.sahkoposti)) + Assertions.assertEquals(viesti.vastaanottajat.get.asScala.map(v => v.getSahkopostiOsoite.get), getVastaanottajatResponse.vastaanottajat.asScala.map(v => v.getSahkoposti)) @WithMockUser(value = "kayttaja", authorities = Array(SecurityConstants.SECURITY_ROOLI_LAHETYS_FULL, SecurityConstants.SECURITY_ROOLI_KATSELU_FULL)) @Test def testGetVastaanottajatSivutus(): Unit = @@ -303,7 +303,7 @@ class IntegraatioTesti extends BaseIntegraatioTesti { .accept(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk).andReturn() val getVastaanottajatResponse = objectMapper.readValue(getResult.getResponse.getContentAsString(StandardCharset.UTF_8), classOf[VastaanottajatSuccessResponse]) - Assertions.assertEquals(vastaanottajat1.map(v => v.sahkopostiOsoite.get), getVastaanottajatResponse.vastaanottajat.asScala.map(v => v.sahkoposti)) + Assertions.assertEquals(vastaanottajat1.map(v => v.sahkopostiOsoite.get), getVastaanottajatResponse.vastaanottajat.asScala.map(v => v.getSahkoposti)) // haetaan seuraavat vastaanottajat, saadaan vastaanottajat2 val getSeuraavatResult = mvc.perform(MockMvcRequestBuilders @@ -311,7 +311,7 @@ class IntegraatioTesti extends BaseIntegraatioTesti { .accept(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk).andReturn() val getSeuraavatResponse = objectMapper.readValue(getSeuraavatResult.getResponse.getContentAsString(StandardCharset.UTF_8), classOf[VastaanottajatSuccessResponse]) - Assertions.assertEquals(vastaanottajat2.map(v => v.sahkopostiOsoite.get), getSeuraavatResponse.vastaanottajat.asScala.map(v => v.sahkoposti)) + Assertions.assertEquals(vastaanottajat2.map(v => v.sahkopostiOsoite.get), getSeuraavatResponse.vastaanottajat.asScala.map(v => v.getSahkoposti)) // vastaanottajia ei enää jäljellä Assertions.assertEquals(Optional.empty, getSeuraavatResponse.seuraavat) @@ -516,7 +516,7 @@ class IntegraatioTesti extends BaseIntegraatioTesti { .andExpect(status().isOk()).andReturn() val vastaanottajaResponse = objectMapper.readValue(vastaanottajaResult.getResponse.getContentAsString, classOf[VastaanottajatSuccessResponse]) - tila = vastaanottajaResponse.vastaanottajat.get(0).tila + tila = vastaanottajaResponse.vastaanottajat.get(0).getTila }, 60.seconds) catch case e: Exception => Assertions.fail("Vastaanottaja ei muuttunut delivery-tilaan sallitussa ajassa") diff --git a/integraatio/src/test/scala/fi/oph/viestinvalitys/ViestinvalitysClientTest.java b/integraatio/src/test/scala/fi/oph/viestinvalitys/ViestinvalitysClientTest.java index 5e86d7cc..ce97813c 100644 --- a/integraatio/src/test/scala/fi/oph/viestinvalitys/ViestinvalitysClientTest.java +++ b/integraatio/src/test/scala/fi/oph/viestinvalitys/ViestinvalitysClientTest.java @@ -1,17 +1,20 @@ package fi.oph.viestinvalitys; import fi.oph.viestinvalitys.vastaanotto.model.*; +import fi.oph.viestinvalitys.vastaanotto.resource.VastaanottajaResponseImpl; import io.netty.handler.codec.http.cookie.Cookie; import org.asynchttpclient.Dsl; import org.asynchttpclient.AsyncHttpClient; import org.asynchttpclient.RequestBuilder; import org.asynchttpclient.Response; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import java.util.Optional; import java.util.List; +import java.util.Iterator; class ViestinvalitysClientTest extends BaseIntegraatioTesti { @@ -83,13 +86,15 @@ public void testLuoViesti() throws Exception { @Test public void testLiitaLiite() throws Exception { - LuoLiiteSuccessResponse liiteResponse = this.getClient().luoLiite(Liite.builder() + ViestinvalitysClient client = this.getClient(); + + LuoLiiteSuccessResponse liiteResponse = client.luoLiite(Liite.builder() .withFileName("test") .withBytes(new byte[] {0}) .withContentType("image/png") .build()); - LuoViestiSuccessResponse viestiResponse = this.getClient().luoViesti(Viesti.builder() + LuoViestiSuccessResponse viestiResponse = client.luoViesti(Viesti.builder() .withOtsikko("otsikko") .withTextSisalto("sisältö") .withKielet("fi") @@ -104,4 +109,36 @@ public void testLiitaLiite() throws Exception { .build()); } + @Test + public void testGetVastaanottajat() throws Exception { + ViestinvalitysClient client = this.getClient(); + + LuoViestiSuccessResponse viestiResponse = client.luoViesti(Viesti.builder() + .withOtsikko("otsikko") + .withTextSisalto("sisältö") + .withKielet("fi") + .withLahettaja(Optional.empty(), "noreply@opintopolku.fi") + .withVastaanottajat(Vastaanottajat.builder() + .withVastaanottaja(Optional.empty(), "vallu.vastaanottaja@example.com") + .withVastaanottaja(Optional.empty(), "veera.vastaanottaja@example.com") + .build()) + .withNormaaliPrioriteetti() + .withSailytysAika(10) + .withLahettavaPalvelu("palvelu") + .build()); + + Iterator> vastaanottajat = client.getVastaanottajat(viestiResponse.getLahetysTunniste(), Optional.of(1)); + + List vastaanottajat1 = vastaanottajat.next(); + Assertions.assertEquals(1, vastaanottajat1.size()); + Assertions.assertEquals("vallu.vastaanottaja@example.com", vastaanottajat1.get(0).getSahkoposti()); + + List vastaanottajat2 = vastaanottajat.next(); + Assertions.assertEquals(1, vastaanottajat2.size()); + Assertions.assertEquals("veera.vastaanottaja@example.com", vastaanottajat2.get(0).getSahkoposti()); + + Assertions.assertFalse(vastaanottajat.hasNext()); + + } + } diff --git a/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.java b/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.java index 860fb9b9..266433b1 100644 --- a/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.java +++ b/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.java @@ -1,9 +1,12 @@ package fi.oph.viestinvalitys; import fi.oph.viestinvalitys.vastaanotto.model.*; -import fi.vm.sade.javautils.nio.cas.impl.CasSessionFetcher; +import fi.oph.viestinvalitys.vastaanotto.resource.VastaanottajaResponseImpl; +import java.util.List; import java.util.UUID; +import java.util.Optional; +import java.util.Iterator; public interface ViestinvalitysClient { @@ -13,6 +16,8 @@ public interface ViestinvalitysClient { public LuoViestiSuccessResponse luoViesti(Viesti viesti) throws ViestinvalitysClientException; + public Iterator> getVastaanottajat(UUID lahetysTunniste, Optional enintaan); + public static EndpointBuilder builder() { return new ViestinvalitysClientBuilderImpl(); } diff --git a/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.scala b/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.scala index 6653013e..67635d26 100644 --- a/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.scala +++ b/kirjasto/src/main/scala/fi.oph.viestinvalitys/ViestinvalitysClient.scala @@ -2,17 +2,18 @@ package fi.oph.viestinvalitys import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper, SerializationFeature} import com.fasterxml.jackson.datatype.jdk8.Jdk8Module +import com.fasterxml.jackson.module.scala.DefaultScalaModule import fi.oph.viestinvalitys import fi.oph.viestinvalitys.ViestinvalitysClient.* -import fi.oph.viestinvalitys.vastaanotto.model.{Lahetys, Liite, LuoLahetysSuccessResponse, LuoLiiteSuccessResponse, LuoViestiSuccessResponse, Viesti} -import fi.oph.viestinvalitys.vastaanotto.resource.{APIConstants, LuoLahetysFailureResponseImpl, LuoLahetysSuccessResponseImpl, LuoLiiteFailureResponseImpl, LuoLiiteSuccessResponseImpl, LuoViestiFailureResponseImpl, LuoViestiSuccessResponseImpl} +import fi.oph.viestinvalitys.vastaanotto.model.{Lahetys, Liite, LuoLahetysSuccessResponse, LuoLiiteSuccessResponse, LuoViestiSuccessResponse, VastaanottajaResponse, Viesti} +import fi.oph.viestinvalitys.vastaanotto.resource.{APIConstants, LuoLahetysFailureResponseImpl, LuoLahetysSuccessResponseImpl, LuoLiiteFailureResponseImpl, LuoLiiteSuccessResponseImpl, LuoViestiFailureResponseImpl, LuoViestiSuccessResponseImpl, VastaanottajaResponseImpl, VastaanottajatFailureResponse, VastaanottajatResponse, VastaanottajatSuccessResponse} import fi.vm.sade.javautils.nio.cas.impl.{CasClientImpl, CasSessionFetcher} import fi.vm.sade.javautils.nio.cas.{CasClient, CasClientBuilder, CasConfig} import org.asynchttpclient.request.body.multipart.ByteArrayPart import org.asynchttpclient.{Dsl, Request, RequestBuilder} import java.util.concurrent.CompletableFuture -import java.util.UUID +import java.util.{Optional, UUID} import scala.jdk.CollectionConverters.* import java.util @@ -20,12 +21,21 @@ class ViestinvalitysClientImpl(casClient: CasClient, endpoint: String, callerId: val objectMapper = { val mapper = new ObjectMapper() + mapper.registerModule(DefaultScalaModule) mapper.registerModule(new Jdk8Module()) mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) mapper.configure(SerializationFeature.INDENT_OUTPUT, true) mapper } + private def getJsonGetRequest(path: String): Request = + new RequestBuilder() + .setUrl(path) + .setMethod("GET") + .setRequestTimeout(10000) + .addHeader("Caller-Id", this.callerId) + .addHeader("Accept", "application/json").build() + private def getJsonPostRequest(path: String, body: Any): Request = new RequestBuilder() .setUrl(this.endpoint + path) @@ -47,6 +57,44 @@ class ViestinvalitysClientImpl(casClient: CasClient, endpoint: String, callerId: val successResponse = objectMapper.readValue(response.getResponseBody, classOf[LuoLahetysSuccessResponseImpl]) successResponse + override def getVastaanottajat(lahetysTunniste: UUID, enintaan: Optional[java.lang.Integer]): util.Iterator[util.List[VastaanottajaResponse]] = + new util.Iterator[util.List[VastaanottajaResponse]]: + + def getNextVastaanottajat(seuraavatUrl: Optional[String], enintaan: Optional[java.lang.Integer]): VastaanottajatSuccessResponse = + val url = { + if(seuraavatUrl.isPresent) + seuraavatUrl.get + else + endpoint + APIConstants.GET_VASTAANOTTAJAT_PATH.replace(APIConstants.LAHETYSTUNNISTE_PARAM_PLACEHOLDER, lahetysTunniste.toString) + enintaan.map(v => "?" + APIConstants.ENINTAAN_PARAM_NAME + "=" + v.toString).orElse("") + } + val response = casClient.executeAndRetryWithCleanSessionOnStatusCodes(getJsonGetRequest(url), util.Set.of(401)).get() + if (response.getStatusCode == 403) + throw new ViestinvalitysClientException(Set.empty.asJava, 403) + if (response.getStatusCode != 200) + val failureResponse = objectMapper.readValue(response.getResponseBody, classOf[VastaanottajatFailureResponse]) + throw new ViestinvalitysClientException(failureResponse.virheet.asScala.toSet.asJava, response.getStatusCode) + + objectMapper.readValue(response.getResponseBody, classOf[VastaanottajatSuccessResponse]) + + var end = false; + var vastaanottajatResponse = this.getNextVastaanottajat(Optional.empty, enintaan) + + override def hasNext: Boolean = + this.vastaanottajatResponse.seuraavat.isPresent + + override def next(): util.List[VastaanottajaResponse] = + if(end) + throw new NoSuchElementException + + val vastaanottajat = this.vastaanottajatResponse.vastaanottajat + if(this.vastaanottajatResponse.seuraavat.isEmpty) + end = true + else + this.vastaanottajatResponse = getNextVastaanottajat(this.vastaanottajatResponse.seuraavat, Optional.empty) + + vastaanottajat + + override def luoLiite(liite: Liite): LuoLiiteSuccessResponse = val request = new RequestBuilder() .setUrl(this.endpoint + APIConstants.LIITTEET_PATH) diff --git a/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/model/VastaanottajaResponse.java b/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/model/VastaanottajaResponse.java new file mode 100644 index 00000000..289218ed --- /dev/null +++ b/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/model/VastaanottajaResponse.java @@ -0,0 +1,23 @@ +package fi.oph.viestinvalitys.vastaanotto.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import fi.oph.viestinvalitys.vastaanotto.resource.VastaanottajaResponseImpl; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.Optional; +import java.util.UUID; + +@JsonDeserialize(as = VastaanottajaResponseImpl.class) +@Schema(implementation = VastaanottajaResponseImpl.class) +public interface VastaanottajaResponse { + + String getTunniste(); + + Optional getNimi(); + + String getSahkoposti(); + + UUID getViestiTunniste(); + + String getTila(); +} diff --git a/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResponses.scala b/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResponses.scala index 7e1b9907..27bfb4ed 100644 --- a/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResponses.scala +++ b/lahetysrajapinta/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResponses.scala @@ -1,7 +1,7 @@ package fi.oph.viestinvalitys.vastaanotto.resource import com.fasterxml.jackson.annotation.JsonInclude -import fi.oph.viestinvalitys.vastaanotto.model.LuoLahetysSuccessResponse +import fi.oph.viestinvalitys.vastaanotto.model.{LuoLahetysSuccessResponse, VastaanottajaResponse} import fi.oph.viestinvalitys.vastaanotto.resource.APIConstants.{ESIMERKKI_LAHETYSTUNNISTE, EXAMPLE_LAHETYSTUNNISTE_VALIDOINTIVIRHE, EXAMPLE_OTSIKKO_VALIDOINTIVIRHE, LAHETYSTUNNISTE_INVALID} import io.swagger.v3.oas.annotations.media.Schema @@ -52,7 +52,7 @@ case class PalautaLahetysFailureResponse( class VastaanottajatResponse() {} @JsonInclude(JsonInclude.Include.NON_ABSENT) -case class VastaanottajaResponse( +case class VastaanottajaResponseImpl( @(Schema@field)(example = "3fa85f64-5717-4562-b3fc-2c963f66afa6") @BeanProperty tunniste: String, @(Schema@field)(example = "Vallu Vastaanottaja") @@ -60,17 +60,23 @@ case class VastaanottajaResponse( @(Schema@field)(example = "vallu.vastaanottaja@example.com") @BeanProperty sahkoposti: String, @(Schema@field)(example = "b4662fcb-a4a0-4747-b4b9-f3e165d9e626") - @BeanProperty viestiTunniste: String, + @BeanProperty viestiTunniste: UUID, @(Schema@field)(example = "BOUNCE") @BeanProperty tila: String - ) + ) extends VastaanottajaResponse { + + def this() = this(null, null, null, null, null) +} @JsonInclude(JsonInclude.Include.NON_ABSENT) case class VastaanottajatSuccessResponse( @BeanProperty vastaanottajat: java.util.List[VastaanottajaResponse], @(Schema@field)(example = "") @BeanProperty seuraavat: Optional[String], - ) extends VastaanottajatResponse + ) extends VastaanottajatResponse { + + def this() = this(null, null) +} case class VastaanottajatFailureResponse( @(Schema@field)(example = EXAMPLE_LAHETYSTUNNISTE_VALIDOINTIVIRHE) diff --git a/lambdat/vastaanotto/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResource.scala b/lambdat/vastaanotto/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResource.scala index 5cb74ab5..1bc068b8 100644 --- a/lambdat/vastaanotto/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResource.scala +++ b/lambdat/vastaanotto/src/main/scala/fi/oph/viestinvalitys/vastaanotto/resource/LahetysResource.scala @@ -199,7 +199,13 @@ class LahetysResource { if(vastaanottajat.isEmpty || kantaOperaatiot.getLahetyksenVastaanottajat(uuid.get, Option.apply(vastaanottajat.last.tunniste), Option.apply(1)).isEmpty) Optional.empty else - val host = s"https://${request.getServerName}" + val protocol = { + if("localhost".equals(request.getServerName)) + "http" + else + "https" + } + val host = s"${protocol}://${request.getServerName}" val port = s"${if (request.getServerPort != 443) ":" + request.getServerPort else ""}" val path = s"${GET_VASTAANOTTAJAT_PATH.replace(LAHETYSTUNNISTE_PARAM_PLACEHOLDER, lahetysTunniste)}" val alkaenParam = s"?${ALKAEN_PARAM_NAME}=${vastaanottajat.last.tunniste}" @@ -208,7 +214,7 @@ class LahetysResource { } ResponseEntity.status(HttpStatus.OK).body(VastaanottajatSuccessResponse( - vastaanottajat.map(vastaanottaja => VastaanottajaResponse(vastaanottaja.tunniste.toString, + vastaanottajat.map(vastaanottaja => VastaanottajaResponseImpl(vastaanottaja.tunniste.toString, Optional.ofNullable(vastaanottaja.kontakti.nimi.getOrElse(null)), vastaanottaja.kontakti.sahkoposti, - vastaanottaja.viestiTunniste.toString, vastaanottaja.tila.toString)).asJava, seuraavatLinkki)) + vastaanottaja.viestiTunniste, vastaanottaja.tila.toString)).asJava, seuraavatLinkki)) } \ No newline at end of file