diff --git a/api/batch/pom.xml b/api/batch/pom.xml index 4b7cfccc..b96296cc 100644 --- a/api/batch/pom.xml +++ b/api/batch/pom.xml @@ -4,11 +4,11 @@ rtd-ms-transaction-filter-api it.gov.pagopa.rtd.ms.transaction_filter.api - 1.3.2 + 1.3.3 rtd-ms-transaction-filter-api-batch - 1.3.2 + 1.3.3 diff --git a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/model/InboundTransaction.java b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/model/InboundTransaction.java index 79db6aee..d721ae97 100644 --- a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/model/InboundTransaction.java +++ b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/model/InboundTransaction.java @@ -1,5 +1,7 @@ package it.gov.pagopa.rtd.transaction_filter.batch.model; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; import lombok.*; import javax.validation.constraints.NotBlank; @@ -84,8 +86,11 @@ /** * Transaction amount + * max value: 999.999.999,99€ */ @NotNull + @Min(value = 0) + @Max(value = 99999999999L) Long amount; /** diff --git a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/TransactionAggregationReaderProcessor.java b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/TransactionAggregationReaderProcessor.java index 99da7959..f560fe5a 100644 --- a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/TransactionAggregationReaderProcessor.java +++ b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/TransactionAggregationReaderProcessor.java @@ -51,7 +51,7 @@ public InboundTransaction process(InboundTransaction inboundTransaction) { } key.setAccountingDate(storeService.flyweightAccountingDate( inboundTransaction.getTrxDate().substring(0, 10))); - boolean dirtyDataFound = storeService.storeAggregate(key, Math.toIntExact(inboundTransaction.getAmount()), inboundTransaction.getVat(), + boolean dirtyDataFound = storeService.storeAggregate(key, inboundTransaction.getAmount(), inboundTransaction.getVat(), inboundTransaction.getPosType()); if (dirtyDataFound) { diff --git a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/tasklet/FileManagementTasklet.java b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/tasklet/FileManagementTasklet.java index a53414b7..87f83745 100644 --- a/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/tasklet/FileManagementTasklet.java +++ b/api/batch/src/main/java/it/gov/pagopa/rtd/transaction_filter/batch/step/tasklet/FileManagementTasklet.java @@ -2,6 +2,7 @@ import it.gov.pagopa.rtd.transaction_filter.service.TransactionWriterService; import java.security.SecureRandom; +import java.util.UUID; import lombok.Data; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -226,7 +227,7 @@ private File getDestionationFileByStatus(String sourceFilePath, boolean isComple if (isCompleted) { String archivalPath = resolver.getResources(successPath)[0].getFile().getAbsolutePath(); DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); - destinationPath = archivalPath + File.separator + SecureRandom.getInstanceStrong().nextLong() + + destinationPath = archivalPath + File.separator + UUID.randomUUID().toString().replace("-", "").substring(0, 20) + "_" + OffsetDateTime.now().format(fmt) + "_" + filename; } else { String archivalPath = resolver.getResources(uploadPendingPath)[0].getFile().getAbsolutePath(); diff --git a/api/batch/src/test/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/InboundTransactionItemProcessorValidatorTest.java b/api/batch/src/test/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/InboundTransactionItemProcessorValidatorTest.java index 32319d58..2a724245 100644 --- a/api/batch/src/test/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/InboundTransactionItemProcessorValidatorTest.java +++ b/api/batch/src/test/java/it/gov/pagopa/rtd/transaction_filter/batch/step/processor/InboundTransactionItemProcessorValidatorTest.java @@ -229,7 +229,7 @@ void processTransactionWithValidCorrelationId(String correlationId) { } @ParameterizedTest - @ValueSource(longs = {1000, 200000}) + @ValueSource(longs = {0, 1000, 200000, Integer.MAX_VALUE + 1L, 3000000000L, 99999999999L}) void processTransactionWithValidAmount(Long amount) { BDDMockito.doReturn(true).when(storeServiceMock).hasHpan(FAKE_ENROLLED_PAN); BDDMockito.doReturn(FAKE_SALT).when(storeServiceMock).getSalt(); @@ -241,6 +241,17 @@ void processTransactionWithValidAmount(Long amount) { Assertions.assertEquals(amount, outbound.getAmount()); } + @ParameterizedTest + @ValueSource(longs = {-100L, 100000000000L}) + void processTransactionWithInvalidAmount(Long amount) { + BDDMockito.doReturn(true).when(storeServiceMock).hasHpan(FAKE_ENROLLED_PAN); + BDDMockito.doReturn(FAKE_SALT).when(storeServiceMock).getSalt(); + InboundTransaction transaction = fakeInboundTransaction(); + transaction.setAmount(amount); + InboundTransactionItemProcessor processor = new InboundTransactionItemProcessor(storeServiceMock, false); + Assertions.assertThrows(ConstraintViolationException.class, () -> processor.process(transaction)); + } + @ParameterizedTest @ValueSource(strings = {"1234", "412", "15", ""}) void processTransactionWithInvalidAmountCurrencyThrowsException(String amountCurrency) { diff --git a/api/pom.xml b/api/pom.xml index bbae8d53..f19e0fbd 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -4,12 +4,12 @@ rtd-ms-transaction-filter it.gov.pagopa.rtd.ms - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter.api rtd-ms-transaction-filter-api - 1.3.2 + 1.3.3 pom diff --git a/app/pom.xml b/app/pom.xml index de81c68b..b7741d25 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -4,12 +4,12 @@ rtd-ms-transaction-filter it.gov.pagopa.rtd.ms - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter transaction-filter-app - 1.3.2 + 1.3.3 diff --git a/app/src/main/resources/config/application.yml b/app/src/main/resources/config/application.yml index 19db438b..4df16f5b 100644 --- a/app/src/main/resources/config/application.yml +++ b/app/src/main/resources/config/application.yml @@ -110,7 +110,7 @@ batchConfiguration: rest-client: user-agent: prefix: BatchService - version: 1.3.2 + version: 1.3.3 hpan: serviceCode: hpan-service base-url: ${HPAN_SERVICE_URL:https://bpd-dev.azure-api.net:${HPAN_SERVICE_PORT:443}} diff --git a/app/src/main/resources/logback-spring.xml b/app/src/main/resources/logback-spring.xml index de615dc4..c838e8ec 100644 --- a/app/src/main/resources/logback-spring.xml +++ b/app/src/main/resources/logback-spring.xml @@ -14,8 +14,17 @@ - + ${LOG_FILE} + + + ${LOG_FILE}.%d.gz + + + 15 + 100MB + + Ocp-Apim-Subscription-Key\s*:\s*(.*) diff --git a/core/pom.xml b/core/pom.xml index 82bcadc4..99fee3db 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,12 +4,12 @@ rtd-ms-transaction-filter it.gov.pagopa.rtd.ms - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter rtd-ms-transaction-filter-core - 1.3.2 + 1.3.3 diff --git a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreService.java b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreService.java index 1c53e3c9..cec07c1a 100644 --- a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreService.java +++ b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreService.java @@ -75,7 +75,7 @@ public interface StoreService { * @param posType the transaction POS type * @return boolean true if dirty data has been found during aggregation */ - boolean storeAggregate(AggregationKey key, int amount, String vat, String posType); + boolean storeAggregate(AggregationKey key, long amount, String vat, String posType); /** * Get the aggregate computed over a single aggregation key. diff --git a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceImpl.java b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceImpl.java index a41cebdb..49a667d2 100644 --- a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceImpl.java +++ b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceImpl.java @@ -66,7 +66,7 @@ public boolean hasHpan(String hpan) { } @Override - public synchronized boolean storeAggregate(AggregationKey key, int amount, String vat, String posType) { + public synchronized boolean storeAggregate(AggregationKey key, long amount, String vat, String posType) { aggregates.putIfAbsent(key, new AggregationData()); AggregationData data = aggregates.get(key); data.incNumTrx(); diff --git a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/store/AggregationData.java b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/store/AggregationData.java index e44c2acf..4e0267b2 100644 --- a/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/store/AggregationData.java +++ b/core/src/main/java/it/gov/pagopa/rtd/transaction_filter/service/store/AggregationData.java @@ -15,7 +15,7 @@ public class AggregationData { private int numTrx; // Integer should be fine until we aggregate on daily basis. // Remember to re-evaluate the data type in case the aggregation period would be increased. - private int totalAmount; + private long totalAmount; private String vat = INIT_VAT; private byte posType = INIT_POS_TYPE; @@ -23,8 +23,8 @@ public void incNumTrx() { this.numTrx += 1; } - public void incTotalAmount(int amount) { - this.totalAmount += amount; + public void incTotalAmount(long amount) { + this.totalAmount = Math.addExact(this.totalAmount, amount); } public boolean updateVatOrMarkAsDirty(String vat) { diff --git a/core/src/test/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceTest.java b/core/src/test/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceTest.java index 1ecba2f9..948e67c3 100644 --- a/core/src/test/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceTest.java +++ b/core/src/test/java/it/gov/pagopa/rtd/transaction_filter/service/StoreServiceTest.java @@ -1,5 +1,6 @@ package it.gov.pagopa.rtd.transaction_filter.service; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import ch.qos.logback.classic.Level; @@ -120,7 +121,7 @@ public void getAggregateAfterStoreReturnsData() { storeService.storeAggregate(key, 1000, null, "01"); AggregationData expectedData = new AggregationData(); expectedData.setNumTrx(1); - expectedData.setTotalAmount(1000); + expectedData.setTotalAmount(1000L); expectedData.setPosType((byte)1); expectedData.setVat(null); Assert.assertEquals(expectedData, storeService.getAggregate(key)); @@ -140,7 +141,7 @@ public void getAggregateAfterMultipleStoreReturnsData() { storeService.storeAggregate(key, 2500, null, "01"); AggregationData expectedData = new AggregationData(); expectedData.setNumTrx(2); - expectedData.setTotalAmount(3500); + expectedData.setTotalAmount(3500L); expectedData.setPosType((byte)1); expectedData.setVat(null); Assert.assertEquals(expectedData, storeService.getAggregate(key)); @@ -260,4 +261,39 @@ public void clearAllEmptiesDataStructures() { Assert.assertNull(storeService.getTargetInputFile()); } + @Test + public void testTotalAmountIntegerLimit() { + AggregationKey key = new AggregationKey(); + key.setTerminalId("1"); + key.setMerchantId("1"); + key.setAcquirerId(storeService.flyweightAcquirerId("1")); + key.setSenderCode(storeService.flyweightSenderCode("code")); + key.setFiscalCode("FC"); + key.setAccountingDate(storeService.flyweightAccountingDate("2022-04-07")); + key.setOperationType((byte)0); + + storeService.storeAggregate(key, Integer.MAX_VALUE - 1, "vat", "00"); + storeService.storeAggregate(key, Integer.MAX_VALUE - 1, "vat", "00"); + + assertThat(storeService.getAggregate(key).getTotalAmount()) + .isNotNegative() + .isEqualTo((Integer.MAX_VALUE - 1) * 2L); + } + + @Test + public void whenSumOverflowLongThenThrowArithmeticException() { + AggregationKey key = new AggregationKey(); + key.setTerminalId("1"); + key.setMerchantId("1"); + key.setAcquirerId(storeService.flyweightAcquirerId("1")); + key.setSenderCode(storeService.flyweightSenderCode("code")); + key.setFiscalCode("FC"); + key.setAccountingDate(storeService.flyweightAccountingDate("2022-04-07")); + key.setOperationType((byte)0); + + storeService.storeAggregate(key, Long.MAX_VALUE - 1, "vat", "00"); + + assertThatThrownBy(() -> storeService.storeAggregate(key, Integer.MAX_VALUE - 1, "vat", "00")) + .isInstanceOf(ArithmeticException.class); + } } \ No newline at end of file diff --git a/integration/jpa/pom.xml b/integration/jpa/pom.xml index 5a4dcb5d..4ef5d54a 100644 --- a/integration/jpa/pom.xml +++ b/integration/jpa/pom.xml @@ -4,12 +4,12 @@ rtd-ms-transaction-filter-integration it.gov.pagopa.rtd.ms.transaction_filter - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter.integration rtd-ms-transaction-filter-integration-jpa - 1.3.2 + 1.3.3 diff --git a/integration/pom.xml b/integration/pom.xml index 41523aa6..18c2b1f1 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -4,12 +4,12 @@ rtd-ms-transaction-filter it.gov.pagopa.rtd.ms - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter rtd-ms-transaction-filter-integration - 1.3.2 + 1.3.3 pom diff --git a/integration/rest/pom.xml b/integration/rest/pom.xml index 201e1793..e1e62581 100644 --- a/integration/rest/pom.xml +++ b/integration/rest/pom.xml @@ -4,12 +4,12 @@ it.gov.pagopa.rtd.ms.transaction_filter rtd-ms-transaction-filter-integration - 1.3.2 + 1.3.3 it.gov.pagopa.rtd.ms.transaction_filter.integration rtd-ms-transaction-filter-integration-rest - 1.3.2 + 1.3.3 diff --git a/integration/rest/src/test/java/it/gov/pagopa/rtd/transaction_filter/logger/MaskingPatternLayoutTest.java b/integration/rest/src/test/java/it/gov/pagopa/rtd/transaction_filter/logger/MaskingPatternLayoutTest.java index 33412e42..3589ecb4 100644 --- a/integration/rest/src/test/java/it/gov/pagopa/rtd/transaction_filter/logger/MaskingPatternLayoutTest.java +++ b/integration/rest/src/test/java/it/gov/pagopa/rtd/transaction_filter/logger/MaskingPatternLayoutTest.java @@ -38,7 +38,7 @@ void whenLogContainsSaltThenAnonymizeIt(CapturedOutput output) { String stringWithSalt = "[HpanRestConnector#getSalt] ---> GET https://api.dev.cstar.pagopa.it/rtd/payment-instrument-manager/v2/salt HTTP/1.1\n" + "[HpanRestConnector#getSalt] Ocp-Apim-Subscription-Key: ciao\n" - + "[HpanRestConnector#getSalt] User-Agent: BatchService/1.3.2\n" + + "[HpanRestConnector#getSalt] User-Agent: BatchService/1.3.3\n" + "[HpanRestConnector#getSalt] ---> END HTTP (0-byte body)\n" + "[HpanRestConnector#getSalt] <--- HTTP/1.1 200 OK (57ms)\n" + "[HpanRestConnector#getSalt] connection: keep-alive\n" diff --git a/ops_resources/example_config/application.yml b/ops_resources/example_config/application.yml index c9563b77..0a48df90 100644 --- a/ops_resources/example_config/application.yml +++ b/ops_resources/example_config/application.yml @@ -109,7 +109,7 @@ batchConfiguration: rest-client: user-agent: prefix: BatchService - version: 1.3.2 + version: 1.3.3 hpan: serviceCode: hpan-service base-url: ${HPAN_SERVICE_URL:https://bpd-dev.azure-api.net:${HPAN_SERVICE_PORT:443}} diff --git a/ops_resources/example_config/application_hbsql.yml b/ops_resources/example_config/application_hbsql.yml index 7fc04c75..93c9a19c 100644 --- a/ops_resources/example_config/application_hbsql.yml +++ b/ops_resources/example_config/application_hbsql.yml @@ -87,7 +87,7 @@ batchConfiguration: rest-client: user-agent: prefix: BatchService - version: 1.3.2 + version: 1.3.3 hpan: serviceCode: hpan-service base-url: ${HPAN_SERVICE_URL:https://bpd-dev.azure-api.net:${HPAN_SERVICE_PORT:443}} diff --git a/pom.xml b/pom.xml index 4587589c..feeb55fb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,14 +10,14 @@ it.gov.pagopa.rtd.ms rtd-ms-transaction-filter - 1.3.2 + 1.3.3 pom 1.8 2.7.4 - 42.5.0 + 42.5.1 3.1.4 1.33 2.11.0 @@ -33,7 +33,7 @@ UTF-8 **/enums/**,**/model/**,**/Constants*.java,**/*Config.java,**/*Application.java - 1.3.2 + 1.3.3