diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..913f8c1 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,75 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Java CI with Maven + +on: + push: + branches: [ "main" ] + tags: + - '*' # Trigger per tutti i tag + pull_request: + branches: [ "main" ] + +permissions: + contents: write + id-token: write + actions: write + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set timezone to Europe/Rome + run: sudo timedatectl set-timezone Europe/Rome + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn clean install -P jar -DskipTests -Ddependency-check.skip=true + + - name: Upload artifact to GitHub + uses: actions/upload-artifact@v4.6.0 + with: + name: govpay-gde-api + path: target/govpay-gde-api.war + + release: + runs-on: ubuntu-latest + needs: build + if: startsWith(github.ref, 'refs/tags/') # Esegui solo per i tag + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download artifact from build job + uses: actions/download-artifact@v4 + with: + name: govpay-gde-api + path: target/ # Assicurati che il file venga scaricato nella cartella target + + - name: Rename the artifact file to include the tag + run: cp target/govpay-gde-api.war target/govpay-gde-api-${{ github.ref_name }}.war # Rinominare il file + + - name: List files in target directory + run: ls -l target/ + + - name: Create GitHub release + id: create_release + uses: softprops/action-gh-release@v2.2.1 + with: + files: target/govpay-gde-api-${{ github.ref_name }}.war # Specifica l'artefatto da caricare + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/pom.xml b/pom.xml index 0076838..91420d5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.17 + 3.4.1 it.govpay.gde @@ -17,7 +17,7 @@ GovPay Modulo per la registrazione degli eventi - 11 + 21 ${java.version} ${java.version} ${java.version} @@ -31,10 +31,10 @@ 1.6.0 - 2.11.0 + 2.18.0 - 6.2.1 + 6.6.0 0.2.1 @@ -43,7 +43,6 @@ 1.3.2 - 2.1.2 1.6.2 @@ -52,11 +51,25 @@ 1.5.1.Final - 0.8.8 + 0.8.12 3.5.3 - 1.6.4 - + 1.8.0 + 5.18.2 + + 1.3.2 + + src/main/resources/owasp/falsePositives + + verify + 11.1.1 + true + false + 5 + + 1.5.16 + + 2.3.232 @@ -111,101 +124,33 @@ org.springframework.boot spring-boot-starter-logging - - org.slf4j - slf4j-api - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - jul-to-slf4j - - - org.slf4j - log4j-over-slf4j - - - org.hibernate - hibernate-validator - - - ch.qos.logback - logback-classicr - - + org.springframework.boot - spring-boot-starter-data-jpa + spring-boot-starter-logging - - org.springframework.boot - spring-boot-starter-logging - - - org.slf4j - slf4j-api - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - jul-to-slf4j - - - org.slf4j - log4j-over-slf4j - - - org.hibernate - hibernate-validator - ch.qos.logback - logback-classicr + logback-classic + + + ch.qos.logback + logback-classic + org.springframework.boot spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-logging - - - org.slf4j - slf4j-api - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - jul-to-slf4j - - - org.slf4j - log4j-over-slf4j - - - org.hibernate - hibernate-validator - - - ch.qos.logback - logback-classicr - - + + + + org.springframework.boot + spring-boot-starter-data-jpa @@ -242,6 +187,7 @@ javax.annotation javax.annotation-api + ${javax.annotation-api.version} @@ -278,33 +224,18 @@ commons-lang3 - - org.slf4j - slf4j-api - - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-core - - - org.apache.logging.log4j - log4j-1.2-api - - - - org.apache.logging.log4j - log4j-slf4j-impl - org.springdoc springdoc-openapi-ui ${springdoc.version} + + + org.webjars + swagger-ui + + org.springdoc @@ -315,6 +246,11 @@ org.springframework.boot spring-boot-starter-hateoas + + org.webjars + swagger-ui + ${swagger-ui.version} + @@ -327,6 +263,7 @@ hamcrest-core test + jakarta.json jakarta.json-api @@ -334,10 +271,16 @@ org.glassfish - javax.json - 1.1.4 + jakarta.json + 2.0.1 test + + org.eclipse.parsson + parsson + 1.0.0 + test + @@ -345,6 +288,7 @@ src/main/resources + true govpay-gde-api @@ -404,6 +348,7 @@ true true true + true ${project.basedir}/target false @@ -433,6 +378,44 @@ + + org.owasp + dependency-check-maven + ${owasp.plugin.version} + + + check owasp + ${owasp} + + ${owasp.plugin.autoUpdate} + ${owasp.plugin.failBuildOnAnyVulnerability} + ALL + + ${owasp.falsePositives.dir}/CVE-2018-14335.xml + + 120000 + 3 + + + aggregate + + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.8.6.0 + + + + com.h3xstream.findsecbugs + findsecbugs-plugin + 1.12.0 + + + + diff --git a/src/main/java/it/govpay/gde/config/WebConfig.java b/src/main/java/it/govpay/gde/config/WebConfig.java new file mode 100644 index 0000000..3099cbb --- /dev/null +++ b/src/main/java/it/govpay/gde/config/WebConfig.java @@ -0,0 +1,43 @@ +package it.govpay.gde.config; + +import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import it.govpay.gde.costanti.Costanti; +import it.govpay.gde.utils.OffsetDateTimeDeserializer; +import it.govpay.gde.utils.OffsetDateTimeSerializer; + + +@Configuration +public class WebConfig { + + @Bean + public ObjectMapper objectMapper() { + // Crea un ObjectMapper con configurazioni personalizzate + ObjectMapper objectMapper = new ObjectMapper(); + + // Imposta il formato delle date + objectMapper.setDateFormat(new SimpleDateFormat(Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX)); + + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + // Aggiungi moduli personalizzati se necessario + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer()); + javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer()); + objectMapper.registerModule(javaTimeModule); + + return objectMapper; + } +} diff --git a/src/main/java/it/govpay/gde/controller/GdeController.java b/src/main/java/it/govpay/gde/controller/GdeController.java index 70934c1..e9e1a2a 100644 --- a/src/main/java/it/govpay/gde/controller/GdeController.java +++ b/src/main/java/it/govpay/gde/controller/GdeController.java @@ -2,11 +2,8 @@ import java.time.OffsetDateTime; -import javax.servlet.http.HttpServletRequest; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.jpa.domain.Specification; import org.springframework.http.HttpHeaders; @@ -24,6 +21,7 @@ import it.govpay.gde.beans.Evento; import it.govpay.gde.beans.ListaEventi; import it.govpay.gde.beans.NuovoEvento; +import it.govpay.gde.beans.PageInfo; import it.govpay.gde.beans.RuoloEvento; import it.govpay.gde.entity.EventoEntity; import it.govpay.gde.exception.ResourceNotFoundException; @@ -33,24 +31,28 @@ import it.govpay.gde.repository.EventoRepository; import it.govpay.gde.repository.LimitOffsetPageRequest; import it.govpay.gde.utils.ListaUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; @Controller -//@RequestMapping("/api/v1") public class GdeController implements EventiApi{ private Logger logger = LoggerFactory.getLogger(GdeController.class); - @Autowired private EventoRepository eventoRepository; - @Autowired - NuovoEventoMapperImpl nuovoEventoMapperImpl; + private NuovoEventoMapperImpl nuovoEventoMapperImpl; + + private EventoMapperImpl eventoMapperImpl; - @Autowired - EventoMapperImpl eventoMapperImpl; + public GdeController(EventoRepository eventoRepository, NuovoEventoMapperImpl nuovoEventoMapperImpl, EventoMapperImpl eventoMapperImpl) { + this.eventoRepository = eventoRepository; + this.nuovoEventoMapperImpl = nuovoEventoMapperImpl; + this.eventoMapperImpl = eventoMapperImpl; + } @Override - public ResponseEntity addEvento(NuovoEvento nuovoEvento) { + public ResponseEntity addEvento(@Valid NuovoEvento nuovoEvento) { this.logger.debug("Salvataggio evento: {}", nuovoEvento); EventoEntity entity = this.nuovoEventoMapperImpl.nuovoEventoToEventoEntity(nuovoEvento); @@ -65,7 +67,7 @@ public ResponseEntity addEvento(NuovoEvento nuovoEvento) { headers.add("Location", ListaUtils.createLocation(curRequest, entity.getId())); - return new ResponseEntity(headers, HttpStatus.CREATED); + return new ResponseEntity<>(headers, HttpStatus.CREATED); } @Override @@ -78,8 +80,13 @@ public ResponseEntity findEventi(Long offset, this.logger.debug("Ricerca eventi..."); - Specification spec = creaFiltriDiRicerca(dataDa, dataA, idDominio, iuv, ccp, idA2A, idPendenza, - categoriaEvento, esito, ruolo, sottotipoEvento, tipoEvento, componente, severitaDa, severitaA); + Specification spec = creaFiltriDiRicercaDate(dataDa, dataA); + + spec = creaFiltriDiRicercaEvento(spec, categoriaEvento, esito, ruolo, sottotipoEvento, tipoEvento, componente); + + spec = creaFiltriDiRicercaDatiPendenza(spec, idDominio, iuv, ccp, idA2A, idPendenza); + + spec = creaFiltriDiRicercaSeverita(spec, severitaDa, severitaA); LimitOffsetPageRequest pageRequest = new LimitOffsetPageRequest(offset, limit, EventoFilters.sort()); @@ -87,7 +94,10 @@ public ResponseEntity findEventi(Long offset, HttpServletRequest curRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); - ListaEventi ret = ListaUtils.buildPaginatedList(eventi, pageRequest.limit, curRequest, new ListaEventi()); + PageInfo pageInfo = new PageInfo(offset,limit); + pageInfo.setTotal(eventi.getTotalElements()); + + ListaEventi ret = ListaUtils.buildPaginatedList(eventi, pageRequest.limit, curRequest, new ListaEventi(pageInfo, null)); for (EventoEntity user : eventi) { ret.addItemsItem(this.eventoMapperImpl.eventoEntityToEvento(user)); @@ -97,11 +107,8 @@ public ResponseEntity findEventi(Long offset, return ResponseEntity.ok(ret); } - - private Specification creaFiltriDiRicerca(OffsetDateTime dataDa, OffsetDateTime dataA, String idDominio, - String iuv, String ccp, String idA2A, String idPendenza, CategoriaEvento categoriaEvento, EsitoEvento esito, - RuoloEvento ruolo, String sottotipoEvento, String tipoEvento, ComponenteEvento componente, - Integer severitaDa, Integer severitaA) { + + private Specification creaFiltriDiRicercaDate(OffsetDateTime dataDa, OffsetDateTime dataA) { Specification spec = EventoFilters.empty(); if(dataDa != null) { @@ -110,6 +117,43 @@ private Specification creaFiltriDiRicerca(OffsetDateTime dataDa, O if(dataA != null) { spec = spec.and(EventoFilters.byDataA(dataA)); } + return spec; + } + + private Specification creaFiltriDiRicercaEvento(Specification spec, CategoriaEvento categoriaEvento, EsitoEvento esito, + RuoloEvento ruolo, String sottotipoEvento, String tipoEvento, ComponenteEvento componente) { + + if (spec == null) { + spec = EventoFilters.empty(); + } + + if(tipoEvento != null) { + spec = spec.and(EventoFilters.byTipoEvento(tipoEvento)); + } + if(sottotipoEvento != null) { + spec = spec.and(EventoFilters.bySottotipoEvento(sottotipoEvento)); + } + if(componente != null) { + spec = spec.and(EventoFilters.byComponenteEvento(componente)); + } + if(categoriaEvento != null) { + spec = spec.and(EventoFilters.byCategoriaEvento(categoriaEvento)); + } + if(esito != null) { + spec = spec.and(EventoFilters.byEsitoEvento(esito)); + } + if(ruolo != null) { + spec = spec.and(EventoFilters.byRuoloEvento(ruolo)); + } + return spec; + } + + private Specification creaFiltriDiRicercaDatiPendenza(Specification spec, String idDominio, + String iuv, String ccp, String idA2A, String idPendenza) { + if (spec == null) { + spec = EventoFilters.empty(); + } + if(idDominio != null) { spec = spec.and(EventoFilters.byIdDominio(idDominio)); } @@ -125,30 +169,21 @@ private Specification creaFiltriDiRicerca(OffsetDateTime dataDa, O if(idPendenza != null) { spec = spec.and(EventoFilters.byIdPendenza(idPendenza)); } + return spec; + } + + private Specification creaFiltriDiRicercaSeverita(Specification spec, Integer severitaDa, Integer severitaA) { + + if (spec == null) { + spec = EventoFilters.empty(); + } + if(severitaDa != null) { spec = spec.and(EventoFilters.bySeveritaDa(severitaDa)); } if(severitaA != null) { spec = spec.and(EventoFilters.bySeveritaA(severitaA)); } - if(tipoEvento != null) { - spec = spec.and(EventoFilters.byTipoEvento(tipoEvento)); - } - if(sottotipoEvento != null) { - spec = spec.and(EventoFilters.bySottotipoEvento(sottotipoEvento)); - } - if(componente != null) { - spec = spec.and(EventoFilters.byComponenteEvento(componente)); - } - if(categoriaEvento != null) { - spec = spec.and(EventoFilters.byCategoriaEvento(categoriaEvento)); - } - if(esito != null) { - spec = spec.and(EventoFilters.byEsitoEvento(esito)); - } - if(ruolo != null) { - spec = spec.and(EventoFilters.byRuoloEvento(ruolo)); - } return spec; } @@ -158,7 +193,7 @@ public ResponseEntity getEventoById(Long id) { ResponseEntity res = this.eventoRepository.findById(id).map(this.eventoMapperImpl::eventoEntityToEvento) .map(ResponseEntity::ok) - .orElseThrow(() -> new ResourceNotFoundException()); + .orElseThrow(ResourceNotFoundException::new); this.logger.debug("Lettura evento completata."); return res; diff --git a/src/main/java/it/govpay/gde/costanti/Costanti.java b/src/main/java/it/govpay/gde/costanti/Costanti.java new file mode 100644 index 0000000..a9b0a80 --- /dev/null +++ b/src/main/java/it/govpay/gde/costanti/Costanti.java @@ -0,0 +1,12 @@ +package it.govpay.gde.costanti; + +public class Costanti { + + private Costanti() { + //donothing + } + + public static final String PATTERN_YYYY_MM_DD_T_HH_MM_SS_MILLIS_VARIABILI_XXX = "yyyy-MM-dd'T'HH:mm:ss[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]XXX]"; + + public static final String PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; +} diff --git a/src/main/java/it/govpay/gde/entity/EventoEntity.java b/src/main/java/it/govpay/gde/entity/EventoEntity.java index b9058c7..bafdd1c 100644 --- a/src/main/java/it/govpay/gde/entity/EventoEntity.java +++ b/src/main/java/it/govpay/gde/entity/EventoEntity.java @@ -1,21 +1,21 @@ package it.govpay.gde.entity; +import java.sql.Types; import java.time.OffsetDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Index; -import javax.persistence.Lob; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - -import org.hibernate.annotations.Type; +import org.hibernate.annotations.JdbcTypeCode; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.Lob; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -88,8 +88,8 @@ public enum EsitoEvento { OK, KO, FAIL } // @Lob // @Convert(converter = DatiPagoPAConverter.class) - @Type(type = "org.hibernate.type.TextType") -// private String descrizione; +// @Type(value = "org.hibernate.type.TextType") + @JdbcTypeCode(Types.LONGVARCHAR) @Column(name = "dati_pago_pa") private String datiPagoPA; @@ -130,14 +130,16 @@ public enum EsitoEvento { OK, KO, FAIL } private String transactionId; @Lob - @Type(type="org.hibernate.type.BinaryType") +// @Type(type="org.hibernate.type.BinaryType") // @Convert(converter = DettaglioRichiestaConverter.class) + @JdbcTypeCode(Types.VARBINARY) @Column(name = "parametri_richiesta") private byte[] parametriRichiesta; @Lob - @Type(type="org.hibernate.type.BinaryType") +// @Type(type="org.hibernate.type.BinaryType") // @Convert(converter = DettaglioRispostaConverter.class) + @JdbcTypeCode(Types.VARBINARY) @Column(name = "parametri_risposta") private byte[] parametriRisposta; diff --git a/src/main/java/it/govpay/gde/exception/handlers/RestResponseEntityExceptionHandler.java b/src/main/java/it/govpay/gde/exception/handlers/RestResponseEntityExceptionHandler.java index c1dea8f..ae204ab 100644 --- a/src/main/java/it/govpay/gde/exception/handlers/RestResponseEntityExceptionHandler.java +++ b/src/main/java/it/govpay/gde/exception/handlers/RestResponseEntityExceptionHandler.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -99,15 +100,14 @@ public final ResponseEntity handleAllInternalExceptions(Throwable ex, We @Override protected ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex, - org.springframework.http.HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpHeaders headers, HttpStatusCode status, WebRequest request) { var error = ex.getBindingResult().getAllErrors().get(0); return buildResponseProblem(HttpStatus.BAD_REQUEST, RestResponseEntityExceptionHandler.extractValidationError(error),request.getHeader(HttpHeaders.ACCEPT)); } - - + @Override - protected ResponseEntity handleHttpMessageNotReadable( - HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + protected ResponseEntity handleHttpMessageNotReadable(HttpMessageNotReadableException ex, + HttpHeaders headers, HttpStatusCode status, WebRequest request) { String msg; if (ex.getCause() instanceof ValueInstantiationException) { @@ -119,13 +119,13 @@ protected ResponseEntity handleHttpMessageNotReadable( } @Override - protected ResponseEntity handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + protected ResponseEntity handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return buildResponseProblem(HttpStatus.BAD_REQUEST,ex.getLocalizedMessage(), request.getHeader(HttpHeaders.ACCEPT)); } @Override - protected ResponseEntity handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + protected ResponseEntity handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return buildResponseProblem(HttpStatus.BAD_REQUEST,ex.getLocalizedMessage(), request.getHeader(HttpHeaders.ACCEPT)); } @@ -136,7 +136,7 @@ protected ResponseEntity handleMissingServletRequestParameter(MissingSer */ @Override protected ResponseEntity handleHttpMediaTypeNotAcceptable( - HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { + HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return buildResponseProblem(HttpStatus.NOT_ACCEPTABLE, ex.getLocalizedMessage(), request.getHeader(HttpHeaders.ACCEPT)); } @@ -144,7 +144,7 @@ protected ResponseEntity handleHttpMediaTypeNotAcceptable( @Override protected ResponseEntity handleExceptionInternal( - Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { + Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatusCode status, WebRequest request) { if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, RequestAttributes.SCOPE_REQUEST); @@ -158,8 +158,7 @@ protected ResponseEntity handleExceptionInternal( * */ public static String extractValidationError(ObjectError error) { - if (error instanceof FieldError) { - var ferror = (FieldError) error; + if (error instanceof FieldError ferror) { return "Field error in object '" + error.getObjectName() + "' on field '" + ferror.getField() + "': rejected value [" + ObjectUtils.nullSafeToString(ferror.getRejectedValue()) + "]; " + diff --git a/src/main/java/it/govpay/gde/repository/EventoFilters.java b/src/main/java/it/govpay/gde/repository/EventoFilters.java index fb2845f..7bb0e30 100644 --- a/src/main/java/it/govpay/gde/repository/EventoFilters.java +++ b/src/main/java/it/govpay/gde/repository/EventoFilters.java @@ -2,9 +2,9 @@ import java.time.OffsetDateTime; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; @@ -121,13 +121,10 @@ public static Specification byEsitoEvento(EsitoEvento esito) { public static Specification byRuoloEvento(RuoloEvento ruolo) { it.govpay.gde.entity.EventoEntity.RuoloEvento r= null; - switch (ruolo) { - case CLIENT: + if(RuoloEvento.CLIENT.equals(ruolo)) { r = it.govpay.gde.entity.EventoEntity.RuoloEvento.C; - break; - case SERVER: + } else { r = it.govpay.gde.entity.EventoEntity.RuoloEvento.S; - break; } return addEqualCondition(EventoEntity_.RUOLO_EVENTO,r); diff --git a/src/main/java/it/govpay/gde/utils/JpaConverterObjectMapperFactory.java b/src/main/java/it/govpay/gde/utils/JpaConverterObjectMapperFactory.java index a61a863..f65f72c 100644 --- a/src/main/java/it/govpay/gde/utils/JpaConverterObjectMapperFactory.java +++ b/src/main/java/it/govpay/gde/utils/JpaConverterObjectMapperFactory.java @@ -1,6 +1,7 @@ package it.govpay.gde.utils; import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; import java.util.TimeZone; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @@ -11,10 +12,12 @@ import com.fasterxml.jackson.databind.util.StdDateFormat; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import it.govpay.gde.costanti.Costanti; + public class JpaConverterObjectMapperFactory { private JpaConverterObjectMapperFactory() {} - private static final String PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + private static final ObjectMapper objectMapper; @@ -23,12 +26,18 @@ private JpaConverterObjectMapperFactory() {} .dateFormat(new StdDateFormat().withColonInTimeZone(true)) // Usa StdDateFormat per supportare il fuso orario con i due punti .timeZone(TimeZone.getTimeZone("Europe/Rome")) .build(); - objectMapper.registerModule(new JavaTimeModule()); + + // Aggiungi moduli personalizzati se necessario + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer()); + javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer()); + objectMapper.registerModule(javaTimeModule); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); objectMapper.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - objectMapper.setDateFormat(new SimpleDateFormat(PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS_SSS_Z)); + objectMapper.setDateFormat(new SimpleDateFormat(Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX)); } diff --git a/src/main/java/it/govpay/gde/utils/ListaUtils.java b/src/main/java/it/govpay/gde/utils/ListaUtils.java index e7fab96..74069dd 100644 --- a/src/main/java/it/govpay/gde/utils/ListaUtils.java +++ b/src/main/java/it/govpay/gde/utils/ListaUtils.java @@ -3,7 +3,7 @@ import java.lang.reflect.Method; import java.util.Map.Entry; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.data.domain.Page; import org.springframework.web.util.DefaultUriBuilderFactory; @@ -53,9 +53,7 @@ public static final T buildPaginatedList( // destList.add(Link.of(lastLink,"last")); } - PageInfo pageInfo = new PageInfo(); - pageInfo.setLimit(limit); - pageInfo.setOffset(startOffset); + PageInfo pageInfo = new PageInfo(startOffset, limit); pageInfo.setTotal(results.getTotalElements()); set(destList, "Page", pageInfo); diff --git a/src/main/java/it/govpay/gde/utils/OffsetDateTimeDeserializer.java b/src/main/java/it/govpay/gde/utils/OffsetDateTimeDeserializer.java new file mode 100644 index 0000000..d64e4ff --- /dev/null +++ b/src/main/java/it/govpay/gde/utils/OffsetDateTimeDeserializer.java @@ -0,0 +1,65 @@ +package it.govpay.gde.utils; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; + +import it.govpay.gde.costanti.Costanti; + +public class OffsetDateTimeDeserializer extends StdScalarDeserializer { + + private transient Logger logger = LoggerFactory.getLogger(OffsetDateTimeDeserializer.class); + + private static final long serialVersionUID = 1L; + + private transient DateTimeFormatter formatterMillis = DateTimeFormatter.ofPattern(Costanti.PATTERN_YYYY_MM_DD_T_HH_MM_SS_MILLIS_VARIABILI_XXX, Locale.getDefault()); + + public OffsetDateTimeDeserializer() { + super(OffsetDateTime.class); + } + + @Override + public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + try { + JsonToken currentToken = jsonParser.getCurrentToken(); + if (currentToken == JsonToken.VALUE_STRING) { + return parseOffsetDateTime(jsonParser.getText(), this.formatterMillis); + } else { + return null; + } + } catch (IOException | DateTimeParseException e) { + throw new IOException(e); + } + } + + public OffsetDateTime parseOffsetDateTime(String value, DateTimeFormatter formatter) { + if (value != null && !value.trim().isEmpty()) { + String dateString = value.trim(); + logger.debug("dateString: {}" , dateString); + try { + return OffsetDateTime.parse(dateString, formatter); + }catch (DateTimeParseException e) { + logger.error("Error parsing date: " + e.getMessage(), e); + ZoneOffset offset = ZoneOffset.ofHoursMinutes(1, 0); // CET (Central European Time) + LocalDateTime localDateTime = LocalDateTime.parse(dateString, formatter); + if (localDateTime != null) { + return OffsetDateTime.of(localDateTime, offset); + } + } + } + + return null; + } +} diff --git a/src/main/java/it/govpay/gde/utils/OffsetDateTimeSerializer.java b/src/main/java/it/govpay/gde/utils/OffsetDateTimeSerializer.java new file mode 100644 index 0000000..93c9c20 --- /dev/null +++ b/src/main/java/it/govpay/gde/utils/OffsetDateTimeSerializer.java @@ -0,0 +1,31 @@ +package it.govpay.gde.utils; + +import java.io.IOException; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; + +import it.govpay.gde.costanti.Costanti; + + +public class OffsetDateTimeSerializer extends StdScalarSerializer { + + private static final long serialVersionUID = 1L; + + private transient DateTimeFormatter formatterMillis = DateTimeFormatter.ofPattern(Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX, Locale.getDefault()); + + public OffsetDateTimeSerializer() { + super(OffsetDateTime.class); + } + + @Override + public void serialize(OffsetDateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException { + String dateTimeAsString = dateTime != null ? this.formatterMillis.format(dateTime) : null; + jsonGenerator.writeString(dateTimeAsString); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d010635..ee1eb78 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -80,6 +80,9 @@ spring.datasource.initialization-mode=always # ------------ LOGGING ------------------- +# Define the log file location +logging.file.dir=/var/log/govpay + #spring.jpa.show-sql=true #spring.jpa.properties.hibernate.format_sql=true diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml deleted file mode 100644 index 70475be..0000000 --- a/src/main/resources/log4j2.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - %p <%d{dd-MM-yyyy HH:mm:ss.SSS}> %C.%M(%L): %m %n %n - /var/log/govpay - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..90d5bcc --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] + %yellow(%C{1}): %msg%n%throwable + + + + + + ${LOG_DIR}/govpay-gde_core.log + + + + + ${LOG_DIR}/govpay-gde_core-%d{yyyy-MM-dd}.log + 30 + + + + + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable + + + + + + ${LOG_DIR}/govpay-gde_spring.log + + + + + ${LOG_DIR}/govpay-gde_spring-%d{yyyy-MM-dd}.log + 30 + + + + + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable + + + + + + ${LOG_DIR}/govpay-gde_hibernate.log + + + + + ${LOG_DIR}/govpay-gde_hibernate-%d{yyyy-MM-dd}.log + 30 + + + + + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/owasp/falsePositives/CVE-2018-14335.xml b/src/main/resources/owasp/falsePositives/CVE-2018-14335.xml new file mode 100644 index 0000000..99df011 --- /dev/null +++ b/src/main/resources/owasp/falsePositives/CVE-2018-14335.xml @@ -0,0 +1,11 @@ + + + + + ^pkg:maven/com\.h2database/h2@.*$ + CVE-2018-14335 + + \ No newline at end of file diff --git a/src/test/java/it/govpay/gde/test/UC_1_FindEventiTest.java b/src/test/java/it/govpay/gde/test/UC_1_FindEventiTest.java index d8e06e9..dba21bb 100644 --- a/src/test/java/it/govpay/gde/test/UC_1_FindEventiTest.java +++ b/src/test/java/it/govpay/gde/test/UC_1_FindEventiTest.java @@ -9,10 +9,6 @@ import java.io.ByteArrayInputStream; -import javax.json.Json; -import javax.json.JsonObject; -import javax.json.JsonReader; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -26,6 +22,9 @@ import it.govpay.gde.Application; import it.govpay.gde.test.costanti.Costanti; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc diff --git a/src/test/java/it/govpay/gde/test/UC_2_GetEventoTest.java b/src/test/java/it/govpay/gde/test/UC_2_GetEventoTest.java index be051ea..02d777f 100644 --- a/src/test/java/it/govpay/gde/test/UC_2_GetEventoTest.java +++ b/src/test/java/it/govpay/gde/test/UC_2_GetEventoTest.java @@ -2,17 +2,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.ByteArrayInputStream; -import javax.json.Json; -import javax.json.JsonArray; -import javax.json.JsonObject; -import javax.json.JsonReader; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -29,6 +23,11 @@ import it.govpay.gde.entity.EventoEntity; import it.govpay.gde.repository.EventoRepository; import it.govpay.gde.test.costanti.Costanti; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc @@ -79,9 +78,9 @@ void UC_2_01_GetEventoOk() throws Exception { assertEquals(3, eventoDetail.getInt("severita")); assertEquals("GovPay", eventoDetail.getString("clusterId")); assertEquals("fb695ba5-dbcb-4e11-bcf6-561bce720521", eventoDetail.getString("transactionId")); - assertNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); - assertNull(eventoDetail.get("datiPagoPA")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRichiesta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); } @@ -117,7 +116,7 @@ void UC_2_03_GetEvento_InvalidId() throws Exception { assertNotNull(problem.getString("detail")); assertEquals(500, problem.getInt("status")); assertEquals("Internal Server Error", problem.getString("title")); - assertEquals("Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: \"XXX\"", problem.getString("detail")); + assertEquals("Method parameter 'id': Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; For input string: \"XXX\"", problem.getString("detail")); assertEquals("https://www.rfc-editor.org/rfc/rfc9110.html#name-500-internal-server-error", problem.getString("type")); // TODO vedere perche' non viene lanciato 400 @@ -139,7 +138,7 @@ void UC_2_04_GetEvento_WrongAccept() throws Exception { assertNotNull(problem.getString("detail")); assertEquals(406, problem.getInt("status")); assertEquals("Not Acceptable", problem.getString("title")); - assertEquals("Could not find acceptable representation", problem.getString("detail")); + assertEquals("No acceptable representation", problem.getString("detail")); assertEquals("https://www.rfc-editor.org/rfc/rfc9110.html#name-406-not-acceptable", problem.getString("type")); } diff --git a/src/test/java/it/govpay/gde/test/UC_3_AddEventoTest.java b/src/test/java/it/govpay/gde/test/UC_3_AddEventoTest.java index aba78e7..bfb0c78 100644 --- a/src/test/java/it/govpay/gde/test/UC_3_AddEventoTest.java +++ b/src/test/java/it/govpay/gde/test/UC_3_AddEventoTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -12,14 +11,8 @@ import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; import java.util.TimeZone; -import javax.json.Json; -import javax.json.JsonArray; -import javax.json.JsonObject; -import javax.json.JsonReader; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -50,6 +43,13 @@ import it.govpay.gde.beans.NuovoEvento; import it.govpay.gde.beans.RuoloEvento; import it.govpay.gde.test.costanti.Costanti; +import it.govpay.gde.utils.OffsetDateTimeDeserializer; +import it.govpay.gde.utils.OffsetDateTimeSerializer; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonValue; @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc @@ -66,12 +66,17 @@ class UC_3_AddEventoTest { @BeforeEach public void init() { - SimpleDateFormat sdf = new SimpleDateFormat(Costanti.PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS); + SimpleDateFormat sdf = new SimpleDateFormat(Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX); sdf.setTimeZone(TimeZone.getTimeZone("Europe/Rome")); sdf.setLenient(false); - + mapper = JsonMapper.builder().build(); - mapper.registerModule(new JavaTimeModule()); + + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer()); + javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer()); + mapper.registerModule(javaTimeModule); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); @@ -134,8 +139,8 @@ void UC_3_01_AddEventoOk() throws Exception { assertEquals(nuovoEvento.getCcp(), eventoDetail.getString("ccp")); assertEquals(nuovoEvento.getClusterId(), eventoDetail.getString("clusterId")); assertEquals(nuovoEvento.getComponente().toString(), eventoDetail.getString("componente")); - assertEquals(nuovoEvento.getDataEvento().format(DateTimeFormatter.ISO_DATE_TIME), eventoDetail.getString("dataEvento")); - assertNull(eventoDetail.get("datiPagoPA")); + assertEquals(nuovoEvento.getDataEvento().format(Costanti.DEFAULT_FORMATTER), eventoDetail.getString("dataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); assertEquals(nuovoEvento.getDettaglioEsito(), eventoDetail.getString("dettaglioEsito")); assertEquals(nuovoEvento.getDurataEvento().intValue(), eventoDetail.getInt("durataEvento")); assertEquals(nuovoEvento.getEsito().toString(), eventoDetail.getString("esito")); @@ -147,8 +152,8 @@ void UC_3_01_AddEventoOk() throws Exception { assertEquals(nuovoEvento.getIdRiconciliazione(), eventoDetail.getInt("idRiconciliazione")); assertEquals(nuovoEvento.getIdTracciato(), eventoDetail.getInt("idTracciato")); assertEquals(nuovoEvento.getIuv(), eventoDetail.getString("iuv")); - assertNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRichiesta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); assertEquals(nuovoEvento.getRuolo().toString(), eventoDetail.getString("ruolo")); assertEquals(nuovoEvento.getSeverita(), eventoDetail.getInt("severita")); assertEquals(nuovoEvento.getSottotipoEsito(), eventoDetail.getString("sottotipoEsito")); @@ -227,7 +232,7 @@ void UC_3_02_AddEvento_DatiPagoPAOk() throws Exception { assertEquals(nuovoEvento.getCcp(), eventoDetail.getString("ccp")); assertEquals(nuovoEvento.getClusterId(), eventoDetail.getString("clusterId")); assertEquals(nuovoEvento.getComponente().toString(), eventoDetail.getString("componente")); - assertEquals(nuovoEvento.getDataEvento().format(DateTimeFormatter.ISO_DATE_TIME), eventoDetail.getString("dataEvento")); + assertEquals(nuovoEvento.getDataEvento().format(Costanti.DEFAULT_FORMATTER), eventoDetail.getString("dataEvento")); assertNotNull(eventoDetail.get("datiPagoPA")); assertEquals(nuovoEvento.getDettaglioEsito(), eventoDetail.getString("dettaglioEsito")); assertEquals(nuovoEvento.getDurataEvento().intValue(), eventoDetail.getInt("durataEvento")); @@ -240,15 +245,15 @@ void UC_3_02_AddEvento_DatiPagoPAOk() throws Exception { assertEquals(nuovoEvento.getIdRiconciliazione(), eventoDetail.getInt("idRiconciliazione")); assertEquals(nuovoEvento.getIdTracciato(), eventoDetail.getInt("idTracciato")); assertEquals(nuovoEvento.getIuv(), eventoDetail.getString("iuv")); - assertNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRichiesta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); assertEquals(nuovoEvento.getRuolo().toString(), eventoDetail.getString("ruolo")); assertEquals(nuovoEvento.getSeverita(), eventoDetail.getInt("severita")); assertEquals(nuovoEvento.getSottotipoEsito(), eventoDetail.getString("sottotipoEsito")); assertEquals(nuovoEvento.getSottotipoEvento(), eventoDetail.getString("sottotipoEvento")); assertEquals(nuovoEvento.getTipoEvento(), eventoDetail.getString("tipoEvento")); assertEquals(nuovoEvento.getTransactionId(), eventoDetail.getString("transactionId")); - + JsonObject datiPagoPADetail = eventoDetail.getJsonObject("datiPagoPA"); assertEquals(datiPagoPA.getIdCanale(), datiPagoPADetail.getString("idCanale")); assertEquals(datiPagoPA.getIdDominio(), datiPagoPADetail.getString("idDominio")); @@ -265,7 +270,7 @@ void UC_3_02_AddEvento_DatiPagoPAOk() throws Exception { assertEquals(datiPagoPA.getSct(), datiPagoPADetail.getString("sct")); assertEquals(datiPagoPA.getTipoVersamento(), datiPagoPADetail.getString("tipoVersamento")); } - + @Test void UC_3_03_AddEvento_ParametriRichiestaOk() throws Exception { NuovoEvento nuovoEvento = new NuovoEvento(); @@ -288,8 +293,7 @@ void UC_3_03_AddEvento_ParametriRichiestaOk() throws Exception { nuovoEvento.setIuv("iuv"); DettaglioRichiesta parametriRichiesta = new DettaglioRichiesta(); parametriRichiesta.setDataOraRichiesta(OffsetDateTime.now()); - Header header = new Header(); - header.setNome("Accept"); + Header header = new Header("Accept"); header.setValore("application/json"); parametriRichiesta.addHeadersItem(header ); parametriRichiesta.setMethod("GET"); @@ -332,8 +336,8 @@ void UC_3_03_AddEvento_ParametriRichiestaOk() throws Exception { assertEquals(nuovoEvento.getCcp(), eventoDetail.getString("ccp")); assertEquals(nuovoEvento.getClusterId(), eventoDetail.getString("clusterId")); assertEquals(nuovoEvento.getComponente().toString(), eventoDetail.getString("componente")); - assertEquals(nuovoEvento.getDataEvento().format(DateTimeFormatter.ISO_DATE_TIME), eventoDetail.getString("dataEvento")); - assertNull(eventoDetail.get("datiPagoPA")); + assertEquals(nuovoEvento.getDataEvento().format(Costanti.DEFAULT_FORMATTER), eventoDetail.getString("dataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); assertEquals(nuovoEvento.getDettaglioEsito(), eventoDetail.getString("dettaglioEsito")); assertEquals(nuovoEvento.getDurataEvento().intValue(), eventoDetail.getInt("durataEvento")); assertEquals(nuovoEvento.getEsito().toString(), eventoDetail.getString("esito")); @@ -346,31 +350,31 @@ void UC_3_03_AddEvento_ParametriRichiestaOk() throws Exception { assertEquals(nuovoEvento.getIdTracciato(), eventoDetail.getInt("idTracciato")); assertEquals(nuovoEvento.getIuv(), eventoDetail.getString("iuv")); assertNotNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); assertEquals(nuovoEvento.getRuolo().toString(), eventoDetail.getString("ruolo")); assertEquals(nuovoEvento.getSeverita(), eventoDetail.getInt("severita")); assertEquals(nuovoEvento.getSottotipoEsito(), eventoDetail.getString("sottotipoEsito")); assertEquals(nuovoEvento.getSottotipoEvento(), eventoDetail.getString("sottotipoEvento")); assertEquals(nuovoEvento.getTipoEvento(), eventoDetail.getString("tipoEvento")); assertEquals(nuovoEvento.getTransactionId(), eventoDetail.getString("transactionId")); - + JsonObject parametriRichiestaDetail = eventoDetail.getJsonObject("parametriRichiesta"); - assertEquals(parametriRichiesta.getDataOraRichiesta().format(DateTimeFormatter.ISO_DATE_TIME), parametriRichiestaDetail.getString("dataOraRichiesta")); + assertEquals(parametriRichiesta.getDataOraRichiesta().format(Costanti.DEFAULT_FORMATTER), parametriRichiestaDetail.getString("dataOraRichiesta")); assertNotNull(parametriRichiestaDetail.get("headers")); assertEquals(parametriRichiesta.getMethod(), parametriRichiestaDetail.getString("method")); assertEquals(parametriRichiesta.getPayload(), parametriRichiestaDetail.getString("payload")); assertEquals(parametriRichiesta.getPrincipal(), parametriRichiestaDetail.getString("principal")); assertEquals(parametriRichiesta.getUrl(), parametriRichiestaDetail.getString("url")); assertEquals(parametriRichiesta.getUtente(), parametriRichiestaDetail.getString("utente")); - + JsonArray headersDetail = parametriRichiestaDetail.getJsonArray("headers"); assertEquals(1, headersDetail.size()); JsonObject headerDetail = headersDetail.getJsonObject(0); - + assertEquals(header.getNome(), headerDetail.getString("nome")); assertEquals(header.getValore(), headerDetail.getString("valore")); } - + @Test void UC_3_04_AddEvento_ParametriRispostaOk() throws Exception { NuovoEvento nuovoEvento = new NuovoEvento(); @@ -393,13 +397,12 @@ void UC_3_04_AddEvento_ParametriRispostaOk() throws Exception { nuovoEvento.setIuv("iuv"); DettaglioRisposta parametriRisposta = new DettaglioRisposta(); parametriRisposta.setDataOraRisposta(OffsetDateTime.now()); - Header header = new Header(); - header.setNome("ContentType"); + Header header = new Header("ContentType"); header.setValore("application/json"); parametriRisposta.addHeadersItem(header ); parametriRisposta.setPayload("{}"); parametriRisposta.setStatus(BigDecimal.valueOf(200)); -// nuovoEvento.setParametriRichiesta(parametriRichiesta ); + // nuovoEvento.setParametriRichiesta(parametriRichiesta ); nuovoEvento.setParametriRisposta(parametriRisposta); nuovoEvento.setRuolo(RuoloEvento.CLIENT); nuovoEvento.setSeverita(1); @@ -434,8 +437,8 @@ void UC_3_04_AddEvento_ParametriRispostaOk() throws Exception { assertEquals(nuovoEvento.getCcp(), eventoDetail.getString("ccp")); assertEquals(nuovoEvento.getClusterId(), eventoDetail.getString("clusterId")); assertEquals(nuovoEvento.getComponente().toString(), eventoDetail.getString("componente")); - assertEquals(nuovoEvento.getDataEvento().format(DateTimeFormatter.ISO_DATE_TIME), eventoDetail.getString("dataEvento")); - assertNull(eventoDetail.get("datiPagoPA")); + assertEquals(nuovoEvento.getDataEvento().format(Costanti.DEFAULT_FORMATTER), eventoDetail.getString("dataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); assertEquals(nuovoEvento.getDettaglioEsito(), eventoDetail.getString("dettaglioEsito")); assertEquals(nuovoEvento.getDurataEvento().intValue(), eventoDetail.getInt("durataEvento")); assertEquals(nuovoEvento.getEsito().toString(), eventoDetail.getString("esito")); @@ -447,7 +450,7 @@ void UC_3_04_AddEvento_ParametriRispostaOk() throws Exception { assertEquals(nuovoEvento.getIdRiconciliazione(), eventoDetail.getInt("idRiconciliazione")); assertEquals(nuovoEvento.getIdTracciato(), eventoDetail.getInt("idTracciato")); assertEquals(nuovoEvento.getIuv(), eventoDetail.getString("iuv")); - assertNull(eventoDetail.get("parametriRichiesta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRichiesta")); assertNotNull(eventoDetail.get("parametriRisposta")); assertEquals(nuovoEvento.getRuolo().toString(), eventoDetail.getString("ruolo")); assertEquals(nuovoEvento.getSeverita(), eventoDetail.getInt("severita")); @@ -455,25 +458,25 @@ void UC_3_04_AddEvento_ParametriRispostaOk() throws Exception { assertEquals(nuovoEvento.getSottotipoEvento(), eventoDetail.getString("sottotipoEvento")); assertEquals(nuovoEvento.getTipoEvento(), eventoDetail.getString("tipoEvento")); assertEquals(nuovoEvento.getTransactionId(), eventoDetail.getString("transactionId")); - + JsonObject parametriRispostaDetail = eventoDetail.getJsonObject("parametriRisposta"); - assertEquals(parametriRisposta.getDataOraRisposta().format(DateTimeFormatter.ISO_DATE_TIME), parametriRispostaDetail.getString("dataOraRisposta")); + assertEquals(parametriRisposta.getDataOraRisposta().format(Costanti.DEFAULT_FORMATTER), parametriRispostaDetail.getString("dataOraRisposta")); assertNotNull(parametriRispostaDetail.get("headers")); assertEquals(parametriRisposta.getPayload(), parametriRispostaDetail.getString("payload")); assertEquals(parametriRisposta.getStatus().intValue(), parametriRispostaDetail.getInt("status")); - + JsonArray headersDetail = parametriRispostaDetail.getJsonArray("headers"); assertEquals(1, headersDetail.size()); JsonObject headerDetail = headersDetail.getJsonObject(0); - + assertEquals(header.getNome(), headerDetail.getString("nome")); assertEquals(header.getValore(), headerDetail.getString("valore")); } - + @Test void UC_3_05_AddEvento_CampiNullOk() throws Exception { NuovoEvento nuovoEvento = new NuovoEvento(); -// nuovoEvento.setCategoriaEvento(CategoriaEvento.UTENTE); + // nuovoEvento.setCategoriaEvento(CategoriaEvento.UTENTE); nuovoEvento.setCcp("ccp"); nuovoEvento.setClusterId("GovPay"); nuovoEvento.setComponente(ComponenteEvento.API_BACKOFFICE); @@ -493,7 +496,7 @@ void UC_3_05_AddEvento_CampiNullOk() throws Exception { DettaglioRichiesta parametriRichiesta = new DettaglioRichiesta(); nuovoEvento.setParametriRichiesta(parametriRichiesta); //nuovoEvento.setParametriRisposta(null); -// nuovoEvento.setRuolo(RuoloEvento.CLIENT); + // nuovoEvento.setRuolo(RuoloEvento.CLIENT); nuovoEvento.setSeverita(1); nuovoEvento.setSottotipoEsito("200"); nuovoEvento.setSottotipoEvento("testAddEvento"); @@ -522,12 +525,12 @@ void UC_3_05_AddEvento_CampiNullOk() throws Exception { assertNotNull(eventoDetail); assertEquals(idEvento, eventoDetail.getInt("id")); - assertNull(eventoDetail.get("categoriaEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("categoriaEvento")); assertEquals(nuovoEvento.getCcp(), eventoDetail.getString("ccp")); assertEquals(nuovoEvento.getClusterId(), eventoDetail.getString("clusterId")); assertEquals(nuovoEvento.getComponente().toString(), eventoDetail.getString("componente")); - assertEquals(nuovoEvento.getDataEvento().format(DateTimeFormatter.ISO_DATE_TIME), eventoDetail.getString("dataEvento")); - assertNull(eventoDetail.get("datiPagoPA")); + assertEquals(nuovoEvento.getDataEvento().format(Costanti.DEFAULT_FORMATTER), eventoDetail.getString("dataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); assertEquals(nuovoEvento.getDettaglioEsito(), eventoDetail.getString("dettaglioEsito")); assertEquals(nuovoEvento.getDurataEvento().intValue(), eventoDetail.getInt("durataEvento")); assertEquals(nuovoEvento.getEsito().toString(), eventoDetail.getString("esito")); @@ -540,15 +543,15 @@ void UC_3_05_AddEvento_CampiNullOk() throws Exception { assertEquals(nuovoEvento.getIdTracciato(), eventoDetail.getInt("idTracciato")); assertEquals(nuovoEvento.getIuv(), eventoDetail.getString("iuv")); assertNotNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); - assertNull(eventoDetail.get("ruolo")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("ruolo")); assertEquals(nuovoEvento.getSeverita(), eventoDetail.getInt("severita")); assertEquals(nuovoEvento.getSottotipoEsito(), eventoDetail.getString("sottotipoEsito")); assertEquals(nuovoEvento.getSottotipoEvento(), eventoDetail.getString("sottotipoEvento")); assertEquals(nuovoEvento.getTipoEvento(), eventoDetail.getString("tipoEvento")); assertEquals(nuovoEvento.getTransactionId(), eventoDetail.getString("transactionId")); } - + @Test void UC_3_06_AddEvento_EmptyBody() throws Exception { String body = "{}"; @@ -568,37 +571,38 @@ void UC_3_06_AddEvento_EmptyBody() throws Exception { result = this.mockMvc.perform(get(Costanti.EVENTO_PATH,idEvento)) .andExpect(status().isOk()) .andReturn(); + System.out.println("RES: "+result.getResponse().getContentAsString()); JsonReader reader = Json.createReader(new ByteArrayInputStream(result.getResponse().getContentAsByteArray())); JsonObject eventoDetail = reader.readObject(); assertNotNull(eventoDetail); assertEquals(idEvento, eventoDetail.getInt("id")); - assertNull(eventoDetail.get("categoriaEvento")); - assertNull(eventoDetail.get("ccp")); - assertNull(eventoDetail.get("clusterId")); - assertNull(eventoDetail.get("componente")); - assertNull(eventoDetail.get("dataEvento")); - assertNull(eventoDetail.get("datiPagoPA")); - assertNull(eventoDetail.get("dettaglioEsito")); - assertNull(eventoDetail.get("durataEvento")); - assertNull(eventoDetail.get("esito")); - assertNull(eventoDetail.get("idA2A")); - assertNull(eventoDetail.get("idDominio")); - assertNull(eventoDetail.get("idFr")); - assertNull(eventoDetail.get("idPagamento")); - assertNull(eventoDetail.get("idPendenza")); - assertNull(eventoDetail.get("idRiconciliazione")); - assertNull(eventoDetail.get("idTracciato")); - assertNull(eventoDetail.get("iuv")); - assertNull(eventoDetail.get("parametriRichiesta")); - assertNull(eventoDetail.get("parametriRisposta")); - assertNull(eventoDetail.get("ruolo")); - assertNull(eventoDetail.get("severita")); - assertNull(eventoDetail.get("sottotipoEsito")); - assertNull(eventoDetail.get("sottotipoEvento")); - assertNull(eventoDetail.get("tipoEvento")); - assertNull(eventoDetail.get("transactionId")); - - + assertEquals(JsonValue.NULL, eventoDetail.get("categoriaEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("ccp")); + assertEquals(JsonValue.NULL, eventoDetail.get("clusterId")); + assertEquals(JsonValue.NULL, eventoDetail.get("componente")); + assertEquals(JsonValue.NULL, eventoDetail.get("dataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("datiPagoPA")); + assertEquals(JsonValue.NULL, eventoDetail.get("dettaglioEsito")); + assertEquals(JsonValue.NULL, eventoDetail.get("durataEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("esito")); + assertEquals(JsonValue.NULL, eventoDetail.get("idA2A")); + assertEquals(JsonValue.NULL, eventoDetail.get("idDominio")); + assertEquals(JsonValue.NULL, eventoDetail.get("idFr")); + assertEquals(JsonValue.NULL, eventoDetail.get("idPagamento")); + assertEquals(JsonValue.NULL, eventoDetail.get("idPendenza")); + assertEquals(JsonValue.NULL, eventoDetail.get("idRiconciliazione")); + assertEquals(JsonValue.NULL, eventoDetail.get("idTracciato")); + assertEquals(JsonValue.NULL, eventoDetail.get("iuv")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRichiesta")); + assertEquals(JsonValue.NULL, eventoDetail.get("parametriRisposta")); + assertEquals(JsonValue.NULL, eventoDetail.get("ruolo")); + assertEquals(JsonValue.NULL, eventoDetail.get("severita")); + assertEquals(JsonValue.NULL, eventoDetail.get("sottotipoEsito")); + assertEquals(JsonValue.NULL, eventoDetail.get("sottotipoEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("tipoEvento")); + assertEquals(JsonValue.NULL, eventoDetail.get("transactionId")); + + } } diff --git a/src/test/java/it/govpay/gde/test/UC_4_AddEventoFailTest.java b/src/test/java/it/govpay/gde/test/UC_4_AddEventoFailTest.java index b0a9ec4..c74b727 100644 --- a/src/test/java/it/govpay/gde/test/UC_4_AddEventoFailTest.java +++ b/src/test/java/it/govpay/gde/test/UC_4_AddEventoFailTest.java @@ -8,12 +8,9 @@ import java.io.ByteArrayInputStream; import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; import java.util.TimeZone; -import javax.json.Json; -import javax.json.JsonObject; -import javax.json.JsonReader; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -35,6 +32,11 @@ import it.govpay.gde.Application; import it.govpay.gde.test.costanti.Costanti; +import it.govpay.gde.utils.OffsetDateTimeDeserializer; +import it.govpay.gde.utils.OffsetDateTimeSerializer; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc @@ -51,12 +53,17 @@ class UC_4_AddEventoFailTest { @BeforeEach public void init() { - SimpleDateFormat sdf = new SimpleDateFormat(Costanti.PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS); + SimpleDateFormat sdf = new SimpleDateFormat(Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX); sdf.setTimeZone(TimeZone.getTimeZone("Europe/Rome")); sdf.setLenient(false); - + mapper = JsonMapper.builder().build(); - mapper.registerModule(new JavaTimeModule()); + + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer()); + javaTimeModule.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer()); + mapper.registerModule(javaTimeModule); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); @@ -104,7 +111,7 @@ void UC_4_02_AddEvento_WrongContentType() throws Exception { assertNotNull(problem.getString("detail")); assertEquals(400, problem.getInt("status")); assertEquals("Bad Request", problem.getString("title")); - assertTrue(problem.getString("detail").contains("Content type 'text/html' not supported")); + assertTrue(problem.getString("detail").contains("Content-Type 'text/html' is not supported")); assertEquals("https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request", problem.getString("type")); } @@ -126,7 +133,7 @@ void UC_4_03_AddEvento_Wrong_CategoriaEvento() throws Exception { assertNotNull(problem.getString("detail")); assertEquals(400, problem.getInt("status")); assertEquals("Bad Request", problem.getString("title")); - assertTrue(problem.getString("detail").contains("Cannot construct instance of `it.govpay.gde.beans.CategoriaEvento`, problem: Unexpected value 'XXX'\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 20] (through reference chain: it.govpay.gde.beans.NuovoEvento[\"categoriaEvento\"])")); + assertTrue(problem.getString("detail").contains("Cannot construct instance of `it.govpay.gde.beans.CategoriaEvento`, problem: Unexpected value 'XXX'\n at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 20] (through reference chain: it.govpay.gde.beans.NuovoEvento[\"categoriaEvento\"])")); assertEquals("https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request", problem.getString("type")); } @@ -145,9 +152,9 @@ void UC_4_04_AddEvento_Wrong_TipoEvento() throws Exception { .andReturn(); JsonReader reader = Json.createReader(new ByteArrayInputStream(result.getResponse().getContentAsByteArray())); JsonObject problem = reader.readObject(); - assertNotNull(problem.getString("type")); - assertNotNull(problem.getString("title")); - assertNotNull(problem.getString("detail")); + assertNotNull(problem.get("type")); + assertNotNull(problem.get("title")); + assertNotNull(problem.get("detail")); assertEquals(503, problem.getInt("status")); assertEquals("Service Unavailable", problem.getString("title")); assertEquals("Request can't be satisfaied at the moment", problem.getString("detail")); diff --git a/src/test/java/it/govpay/gde/test/costanti/Costanti.java b/src/test/java/it/govpay/gde/test/costanti/Costanti.java index a57aab4..e567a8e 100644 --- a/src/test/java/it/govpay/gde/test/costanti/Costanti.java +++ b/src/test/java/it/govpay/gde/test/costanti/Costanti.java @@ -1,13 +1,16 @@ package it.govpay.gde.test.costanti; +import java.time.format.DateTimeFormatter; + public class Costanti { public static final String API_BASE_PATH = ""; public static final String EVENTI_PATH = API_BASE_PATH + "/eventi"; public static final String EVENTO_PATH = EVENTI_PATH + "/{id}"; - public static final String PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - public static final String PATTERN_DATA_JSON_YYYY_MM_DD_T_HH_MM_SS = "yyyy-MM-dd'T'HH:mm:ss"; + public static final String PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX = it.govpay.gde.costanti.Costanti.PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX; + + public static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern(PATTERN_TIMESTAMP_3_YYYY_MM_DD_T_HH_MM_SS_SSSXXX); public static final String ID_DOMINIO_1 = "12345678901"; diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..39cfc5e --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,37 @@ + + + + + + + + + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable + + + + + + + + + + + + + + + + + + + + + + + + +