From 615f97d5f44abce1fec51dbb04ce98609283a2bd Mon Sep 17 00:00:00 2001 From: macacia Date: Tue, 26 Nov 2024 11:16:32 +0100 Subject: [PATCH 01/17] P4ADEV-1545 FdRIngestionActity added interface implementation and its Service/DAO/DTO --- .../fdr/FdRIngestionActivityImpl.java | 63 +++++++++++++++++++ .../service/FlowHandlerRetrieverService.java | 27 ++++++++ .../payhub/activities/dao/FlowHandlerDao.java | 13 ++++ .../activities/dto/fdr/FlowHandlerDTO.java | 37 +++++++++++ 4 files changed, 140 insertions(+) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java new file mode 100644 index 00000000..2bc1e710 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java @@ -0,0 +1,63 @@ +package it.gov.pagopa.payhub.activities.activity.fdr; + +import it.gov.pagopa.payhub.activities.activity.fdr.service.FlowHandlerRetrieverService; +import it.gov.pagopa.payhub.activities.dto.fdr.FdRIngestionActivityResult; +import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Slf4j +public class FdRIngestionActivityImpl implements FdRIngestionActivity { + private final FlowHandlerRetrieverService flowHandlerRetrieverService; + + public FdRIngestionActivityImpl(FlowHandlerRetrieverService flowHandlerRetrieverService) { + this.flowHandlerRetrieverService = flowHandlerRetrieverService; + } + + @Override + public FdRIngestionActivityResult processFile(String ingestionFlowId) { + List iufList = new ArrayList<>(); + boolean success = true; + + try { + FlowHandlerDTO flowHandlerDTO = flowHandlerRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); + // Creazione directory temporanea + + // Validazione file + + + // Decifratura + + + // Controllo sicurezza zip + + + // Unzip + + + // Validazione XSD e unmarshalling + + + // Lettura e processazione file + + + // Sposta file in archivio + + } catch (Exception e) { + log.error("Errore durante il processamento del file {}: {}", ingestionFlowId, e.getMessage()); + success = false; + + // Sposta file nella directory di errore + } finally { + // Pulizia directory temporanea + + + return new FdRIngestionActivityResult(iufList, success); + } + + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java new file mode 100644 index 00000000..fed7e875 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java @@ -0,0 +1,27 @@ +package it.gov.pagopa.payhub.activities.activity.fdr.service; + +import it.gov.pagopa.payhub.activities.dao.FlowHandlerDao; +import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; +import it.gov.pagopa.payhub.activities.exception.OperatorNotAuthorizedException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +@Slf4j +public class FlowHandlerRetrieverService { + + private final FlowHandlerDao flowHandlerDao; + + public FlowHandlerRetrieverService(FlowHandlerDao flowHandlerDao) { + this.flowHandlerDao = flowHandlerDao; + } + + public FlowHandlerDTO getByFlowId(Long ingestionFlowId) { + Optional flowHandler = flowHandlerDao.getFlowHandler(ingestionFlowId); + + return flowHandler + .orElseThrow(() -> new OperatorNotAuthorizedException("Cannot found flowHandler having id: "+ ingestionFlowId)); + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java b/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java new file mode 100644 index 00000000..a435a95f --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java @@ -0,0 +1,13 @@ +package it.gov.pagopa.payhub.activities.dao; + +import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; + +import java.util.Optional; + +public interface FlowHandlerDao { + + /** + * * It will return the requested FlowHandlerDTO entity from its id + * */ + Optional getFlowHandler(Long ingestionFlowId); +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java b/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java new file mode 100644 index 00000000..02e09346 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java @@ -0,0 +1,37 @@ +package it.gov.pagopa.payhub.activities.dto.fdr; + +import it.gov.pagopa.payhub.activities.dto.OrganizationDTO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.sql.Timestamp; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class FlowHandlerDTO { + private Long flowHandlerId; + private int version; + private OrganizationDTO orgId; + private String PspIdentifier; + private String flowIdentifierCode; + private Timestamp flowDateTime; + private String flowType; + private String flowTypeCode; + private String operatorName; + private String status; + private String filePathName; + private String fileName; + private Long downloadedFileSize; + private String requestTokenCode; + private Timestamp creationDate; + private Timestamp lastChangeDate; + private String fileSourceCode; + private String descriptionFileNameScraps; + private String errorCode; + private Long TotalRowsNumber; + private Long numberLinesImportedCorrectly; +} From 9e0ada7eb50418582b2306996f1d5101ff724ab3 Mon Sep 17 00:00:00 2001 From: macacia Date: Tue, 26 Nov 2024 12:41:34 +0100 Subject: [PATCH 02/17] P4ADEV-1545 FdRIngestionActity naming refactoring --- .../fdr/FdRIngestionActivityImpl.java | 63 ------------------- .../service/FlowHandlerRetrieverService.java | 27 -------- .../FdRIngestionActivity.java | 4 +- .../FdRIngestionActivityImpl.java | 63 +++++++++++++++++++ .../SendEmailIngestionFlowActivity.java | 2 +- .../UpdateIngestionFlowStatusActivity.java | 2 +- .../IngestionFlowRetrieverService.java | 27 ++++++++ .../payhub/activities/dao/FlowHandlerDao.java | 13 ---- .../activities/dao/IngestionFlowDao.java | 13 ++++ .../FdRIngestionActivityResult.java | 2 +- .../IngestionFlowDTO.java} | 4 +- .../IngestionFlowNotFoundException.java | 6 ++ 12 files changed, 116 insertions(+), 110 deletions(-) delete mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java delete mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java rename src/main/java/it/gov/pagopa/payhub/activities/activity/{fdr => reportingflow}/FdRIngestionActivity.java (76%) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java rename src/main/java/it/gov/pagopa/payhub/activities/activity/{fdr => reportingflow}/SendEmailIngestionFlowActivity.java (90%) rename src/main/java/it/gov/pagopa/payhub/activities/activity/{fdr => reportingflow}/UpdateIngestionFlowStatusActivity.java (89%) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java delete mode 100644 src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/dao/IngestionFlowDao.java rename src/main/java/it/gov/pagopa/payhub/activities/dto/{fdr => reportingflow}/FdRIngestionActivityResult.java (87%) rename src/main/java/it/gov/pagopa/payhub/activities/dto/{fdr/FlowHandlerDTO.java => reportingflow/IngestionFlowDTO.java} (90%) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/exception/IngestionFlowNotFoundException.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java deleted file mode 100644 index 2bc1e710..00000000 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivityImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -package it.gov.pagopa.payhub.activities.activity.fdr; - -import it.gov.pagopa.payhub.activities.activity.fdr.service.FlowHandlerRetrieverService; -import it.gov.pagopa.payhub.activities.dto.fdr.FdRIngestionActivityResult; -import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; - -@Service -@Slf4j -public class FdRIngestionActivityImpl implements FdRIngestionActivity { - private final FlowHandlerRetrieverService flowHandlerRetrieverService; - - public FdRIngestionActivityImpl(FlowHandlerRetrieverService flowHandlerRetrieverService) { - this.flowHandlerRetrieverService = flowHandlerRetrieverService; - } - - @Override - public FdRIngestionActivityResult processFile(String ingestionFlowId) { - List iufList = new ArrayList<>(); - boolean success = true; - - try { - FlowHandlerDTO flowHandlerDTO = flowHandlerRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); - // Creazione directory temporanea - - // Validazione file - - - // Decifratura - - - // Controllo sicurezza zip - - - // Unzip - - - // Validazione XSD e unmarshalling - - - // Lettura e processazione file - - - // Sposta file in archivio - - } catch (Exception e) { - log.error("Errore durante il processamento del file {}: {}", ingestionFlowId, e.getMessage()); - success = false; - - // Sposta file nella directory di errore - } finally { - // Pulizia directory temporanea - - - return new FdRIngestionActivityResult(iufList, success); - } - - } -} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java deleted file mode 100644 index fed7e875..00000000 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/service/FlowHandlerRetrieverService.java +++ /dev/null @@ -1,27 +0,0 @@ -package it.gov.pagopa.payhub.activities.activity.fdr.service; - -import it.gov.pagopa.payhub.activities.dao.FlowHandlerDao; -import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; -import it.gov.pagopa.payhub.activities.exception.OperatorNotAuthorizedException; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@Service -@Slf4j -public class FlowHandlerRetrieverService { - - private final FlowHandlerDao flowHandlerDao; - - public FlowHandlerRetrieverService(FlowHandlerDao flowHandlerDao) { - this.flowHandlerDao = flowHandlerDao; - } - - public FlowHandlerDTO getByFlowId(Long ingestionFlowId) { - Optional flowHandler = flowHandlerDao.getFlowHandler(ingestionFlowId); - - return flowHandler - .orElseThrow(() -> new OperatorNotAuthorizedException("Cannot found flowHandler having id: "+ ingestionFlowId)); - } -} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java similarity index 76% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java index da3b00f2..3a5d17bf 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/FdRIngestionActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java @@ -1,5 +1,5 @@ -package it.gov.pagopa.payhub.activities.activity.fdr; -import it.gov.pagopa.payhub.activities.dto.fdr.FdRIngestionActivityResult; +package it.gov.pagopa.payhub.activities.activity.reportingflow; +import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; /** * Interface for the FdRIngestionActivity. diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java new file mode 100644 index 00000000..1152c3a6 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java @@ -0,0 +1,63 @@ +package it.gov.pagopa.payhub.activities.activity.reportingflow; + +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; +import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Component +public class FdRIngestionActivityImpl implements FdRIngestionActivity { + private final IngestionFlowRetrieverService ingestionFlowRetrieverService; + + public FdRIngestionActivityImpl(IngestionFlowRetrieverService ingestionFlowRetrieverService) { + this.ingestionFlowRetrieverService = ingestionFlowRetrieverService; + } + + @Override + public FdRIngestionActivityResult processFile(String ingestionFlowId) { + List iufList = new ArrayList<>(); + boolean success = true; + + try { + IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); + // Creazione directory temporanea + + // Validazione file + + + // Decifratura + + + // Controllo sicurezza zip + + + // Unzip + + + // Validazione XSD e unmarshalling + + + // Lettura e processazione file + + + // Sposta file in archivio + + } catch (Exception e) { + log.error("Error during IngestionActivity flowId {} due to: {}", ingestionFlowId, e.getMessage()); + success = false; + + // Sposta file nella directory di errore + } finally { + // Pulizia directory temporanea + + + return new FdRIngestionActivityResult(iufList, success); + } + + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/SendEmailIngestionFlowActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java similarity index 90% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/SendEmailIngestionFlowActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java index f5758fab..7a8c94f7 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/SendEmailIngestionFlowActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.fdr; +package it.gov.pagopa.payhub.activities.activity.reportingflow; /** * Interface for SendEmailIngestionFlowActivity. diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/UpdateIngestionFlowStatusActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java similarity index 89% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/UpdateIngestionFlowStatusActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java index 01bfd004..5c3f0856 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/fdr/UpdateIngestionFlowStatusActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.fdr; +package it.gov.pagopa.payhub.activities.activity.reportingflow; /** * Interface for the UpdateIngestionFlowStatusActivity. diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java new file mode 100644 index 00000000..e443cb59 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java @@ -0,0 +1,27 @@ +package it.gov.pagopa.payhub.activities.activity.reportingflow.service; + +import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import it.gov.pagopa.payhub.activities.exception.IngestionFlowNotFoundException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +@Slf4j +public class IngestionFlowRetrieverService { + + private final IngestionFlowDao ingestionFlowDao; + + public IngestionFlowRetrieverService(IngestionFlowDao ingestionFlowDao) { + this.ingestionFlowDao = ingestionFlowDao; + } + + public IngestionFlowDTO getByFlowId(Long ingestionFlowId) { + Optional ingestionFlow = ingestionFlowDao.getIngestionFlow(ingestionFlowId); + + return ingestionFlow + .orElseThrow(() -> new IngestionFlowNotFoundException("Cannot found ingestionFlow having id: "+ ingestionFlowId)); + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java b/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java deleted file mode 100644 index a435a95f..00000000 --- a/src/main/java/it/gov/pagopa/payhub/activities/dao/FlowHandlerDao.java +++ /dev/null @@ -1,13 +0,0 @@ -package it.gov.pagopa.payhub.activities.dao; - -import it.gov.pagopa.payhub.activities.dto.fdr.FlowHandlerDTO; - -import java.util.Optional; - -public interface FlowHandlerDao { - - /** - * * It will return the requested FlowHandlerDTO entity from its id - * */ - Optional getFlowHandler(Long ingestionFlowId); -} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dao/IngestionFlowDao.java b/src/main/java/it/gov/pagopa/payhub/activities/dao/IngestionFlowDao.java new file mode 100644 index 00000000..c663b6d7 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/dao/IngestionFlowDao.java @@ -0,0 +1,13 @@ +package it.gov.pagopa.payhub.activities.dao; + +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; + +import java.util.Optional; + +public interface IngestionFlowDao { + + /** + * * It will return the requested IngestionFlowDTO entity from its id + * */ + Optional getIngestionFlow(Long ingestionFlowId); +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FdRIngestionActivityResult.java b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/FdRIngestionActivityResult.java similarity index 87% rename from src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FdRIngestionActivityResult.java rename to src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/FdRIngestionActivityResult.java index 304a55dd..5c2c51f2 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FdRIngestionActivityResult.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/FdRIngestionActivityResult.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.dto.fdr; +package it.gov.pagopa.payhub.activities.dto.reportingflow; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java similarity index 90% rename from src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java rename to src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java index 02e09346..7d4502db 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/dto/fdr/FlowHandlerDTO.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.dto.fdr; +package it.gov.pagopa.payhub.activities.dto.reportingflow; import it.gov.pagopa.payhub.activities.dto.OrganizationDTO; import lombok.AllArgsConstructor; @@ -12,7 +12,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class FlowHandlerDTO { +public class IngestionFlowDTO { private Long flowHandlerId; private int version; private OrganizationDTO orgId; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/exception/IngestionFlowNotFoundException.java b/src/main/java/it/gov/pagopa/payhub/activities/exception/IngestionFlowNotFoundException.java new file mode 100644 index 00000000..a155398b --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/exception/IngestionFlowNotFoundException.java @@ -0,0 +1,6 @@ +package it.gov.pagopa.payhub.activities.exception; + +public class IngestionFlowNotFoundException extends ActivitiesException { + + public IngestionFlowNotFoundException(String message) { super(message); } +} From bd02bd751d37476e114bba8626453af00a3c3148 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Tue, 26 Nov 2024 20:09:51 +0100 Subject: [PATCH 03/17] send email for ingestion --- build.gradle.kts | 7 +- gradle.lockfile | 5 ++ .../service/AsyncSendMailService.java | 46 ++++++++++ .../service/IngestionFlowMailService.java | 50 +++++++++++ .../exception/SendMailException.java | 7 ++ .../payhub/activities/helper/EmailHelper.java | 21 +++++ .../helper/MailParameterHelper.java | 35 ++++++++ .../payhub/activities/model/MailParams.java | 26 ++++++ src/main/resources/mail-templates.properties | 23 +++++ .../SendEmailIngestionFlowActivityTest.java | 87 +++++++++++++++++++ 10 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/exception/SendMailException.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java create mode 100644 src/main/resources/mail-templates.properties create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 20adac91..47ef125d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -53,7 +53,7 @@ val commonsCompressVersion = "1.27.1" val commonsLang3Version = "3.17.0" val commonsTextVersion = "1.12.0" val jacksonModuleVersion = "2.18.1" - +val jsoupVersion = "1.18.1" dependencies { implementation("org.springframework.boot:spring-boot-starter") @@ -71,6 +71,11 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-parameter-names:$jacksonModuleVersion") + // Mail + implementation("org.springframework.boot:spring-boot-starter-mail") + + implementation("org.jsoup:jsoup:$jsoupVersion") + // Testing testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.junit.jupiter:junit-jupiter-api") diff --git a/gradle.lockfile b/gradle.lockfile index e69d2c27..e18e69b6 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -39,4 +39,9 @@ org.springframework:spring-core:6.1.14=compileClasspath org.springframework:spring-expression:6.1.14=compileClasspath org.springframework:spring-jcl:6.1.14=compileClasspath org.yaml:snakeyaml:2.0=compileClasspath +org.eclipse.angus:jakarta.mail:2.0.3=compileClasspath +org.springframework:spring-context-support:6.1.14=compileClasspath +org.jsoup:jsoup:1.18.1=compileClasspath +jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath +org.springframework.boot:spring-boot-starter-mail:3.3.5=compileClasspath empty= diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java new file mode 100644 index 00000000..b6a3ba35 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java @@ -0,0 +1,46 @@ +package it.gov.pagopa.payhub.activities.activity.reportingflow.service; + +import it.gov.pagopa.payhub.activities.exception.SendMailException; +import it.gov.pagopa.payhub.activities.model.MailParams; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.safety.Safelist; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class AsyncSendMailService { + @Value("${async.sendMail.corePoolSize:2}") + private String corePoolSize; + @Value("${async.sendMail.maxPoolSize:10}") + private String maxPoolSize; + @Value("${async.sendMail.queueCapacity:500}") + private String queueCapacity; + + public void sendMail(JavaMailSender javaMailSender, MailParams mailParams) { + try { + javaMailSender.send( mimeMessage -> { + MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + message.setFrom(mailParams.getEmailFromAddress(), mailParams.getEmailFromName()); + message.setTo(mailParams.getTo()); + if(ArrayUtils.isNotEmpty(mailParams.getCc())) + message.setCc(mailParams.getCc()); + message.setSubject(mailParams.getMailSubject()); + String plainText = Jsoup.clean(mailParams.getHtmlText(), "", Safelist.none(), new Document.OutputSettings().prettyPrint(false)); + message.setText(plainText, mailParams.getHtmlText()); + log.debug("sending mail message"); + } ); + log.info("MAIL has been send"); + } + catch (Exception e) { + log.info("MAIL error"); + throw new SendMailException("Error in mail sending"); + } + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java new file mode 100644 index 00000000..7725dd04 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java @@ -0,0 +1,50 @@ +package it.gov.pagopa.payhub.activities.activity.reportingflow.service; + +import it.gov.pagopa.payhub.activities.exception.SendMailException; +import it.gov.pagopa.payhub.activities.helper.EmailHelper; +import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; +import it.gov.pagopa.payhub.activities.model.MailParams; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.text.StringSubstitutor; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.Properties; + +@Service +@Slf4j +public class IngestionFlowMailService { + private final AsyncSendMailService asyncSendMailService; + private final MailParams mailParams; + private final JavaMailSender javaMailSender; + + public IngestionFlowMailService(AsyncSendMailService asyncSendMailService, MailParams mailParams, JavaMailSender javaMailSender) { + this.asyncSendMailService = asyncSendMailService; + this.mailParams = mailParams; + this.javaMailSender = javaMailSender; + } + + public boolean sendEmail(String ingestionFlowId, boolean success){ + // verify if previous operation is success + if (success){ + try { + // get e-mail parameters + MailParams params = MailParameterHelper.getMailParams(mailParams); + + // send e-mail if there are no errors in parameters + if (params.isSuccess()){ + mailParams.setHtmlText(params.getHtmlText()); + mailParams.setMailSubject(params.getMailSubject()); + mailParams.setIngestionFlowId(ingestionFlowId); + asyncSendMailService.sendMail(javaMailSender, mailParams); + return true; + } + } catch (Exception e) { + throw new SendMailException("Error sending mail for id: "+ingestionFlowId); + } + } + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/payhub/activities/exception/SendMailException.java b/src/main/java/it/gov/pagopa/payhub/activities/exception/SendMailException.java new file mode 100644 index 00000000..3f7d5da7 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/exception/SendMailException.java @@ -0,0 +1,7 @@ +package it.gov.pagopa.payhub.activities.exception; + + +public class SendMailException extends ActivitiesException { + public SendMailException(String message) { super(message); } +} + diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java new file mode 100644 index 00000000..a987db2f --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java @@ -0,0 +1,21 @@ +package it.gov.pagopa.payhub.activities.helper; + +import java.io.InputStream; +import java.util.Properties; + +public class EmailHelper { + /** + * + * @return Properties + */ + public Properties getProperties() { + Properties properties = new Properties(); + try { + InputStream inputStream = EmailHelper.class.getClassLoader().getResourceAsStream("mail-templates.properties"); + properties.load(inputStream); + } catch (Exception e) { + return null; + } + return properties; + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java new file mode 100644 index 00000000..131fdfee --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java @@ -0,0 +1,35 @@ +package it.gov.pagopa.payhub.activities.helper; + +import it.gov.pagopa.payhub.activities.exception.SendMailException; +import it.gov.pagopa.payhub.activities.model.MailParams; +import org.apache.commons.text.StringSubstitutor; +import org.springframework.util.Assert; + +import java.util.Properties; + +public class MailParameterHelper { + public static MailParams getMailParams(MailParams mailParams) { + try { + EmailHelper emailHelper = new EmailHelper(); + Properties mailProperties = emailHelper.getProperties(); + Assert.notEmpty(mailProperties.values(), "Wrong mail configuration"); + String templateName = mailParams.getTemplateName(); + String subject = mailProperties.getProperty("template."+templateName+".subject"); + String body = mailProperties.getProperty("template."+templateName+".body"); + Assert.notNull(subject, "Invalid email template (missing subject) "+templateName); + Assert.notNull(body, "Invalid email template (missing body) "+templateName); + + String mailSubject = StringSubstitutor.replace(subject, mailParams.getParams(), "{", "}"); + String htmlText = StringSubstitutor.replace(body, mailParams.getParams(), "{", "}"); + + MailParams params = new MailParams(); + params.setMailSubject(mailSubject); + params.setHtmlText(htmlText); + params.setSuccess(true); + return params; + } + catch (Exception e) { + throw new SendMailException("Error in mail configuration"); + } + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java b/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java new file mode 100644 index 00000000..0e09fd44 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java @@ -0,0 +1,26 @@ +package it.gov.pagopa.payhub.activities.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Map; + +@Data +@Builder(toBuilder=true) +@NoArgsConstructor +@AllArgsConstructor +public class MailParams implements Serializable { + Map params; + String ingestionFlowId; + String emailFromAddress; + String emailFromName; + String templateName; + String mailSubject; + String htmlText; + boolean success; + String[] to; + String[] cc; +} diff --git a/src/main/resources/mail-templates.properties b/src/main/resources/mail-templates.properties new file mode 100644 index 00000000..db5c9712 --- /dev/null +++ b/src/main/resources/mail-templates.properties @@ -0,0 +1,23 @@ +template.mail-importFlussoRendicontazione-ok.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-ok.body= \ +Gentile Utente,
\n \ +questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ +Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ +

Di seguito il testo del messaggio: {testoMail}

\n\n \ +{dataAttuale} + +template.mail-importFlussoRendicontazione-scarti.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-scarti.body= \ +Gentile Utente,
\n \ +questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ +Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ +

Di seguito il testo del messaggio: {testoMail}

\n\n \ +{dataAttuale} + +template.mail-importFlussoRendicontazione-error.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-error.body= \ +Gentile Utente,
\n \ +questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ +Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ +

Di seguito il testo del messaggio: {testoMail}

\n\n \ +{dataAttuale} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java new file mode 100644 index 00000000..f2814fbf --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -0,0 +1,87 @@ +package it.gov.pagopa.payhub.activities.activity; + +import com.sun.jdi.LongValue; +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowMailService; +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; +import it.gov.pagopa.payhub.activities.dao.DebtPositionTypeOrgDao; +import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; +import it.gov.pagopa.payhub.activities.dto.OrganizationDTO; +import it.gov.pagopa.payhub.activities.dto.debtposition.DebtPositionTypeOrgDTO; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; + +import it.gov.pagopa.payhub.activities.model.MailParams; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.HashMap; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class SendEmailIngestionFlowActivityTest { + + @Mock + IngestionFlowRetrieverService ingestionFlowRetrieverService; + + @Mock + private IngestionFlowDao ingestionFlowDao; + + @Mock + AsyncSendMailService asyncSendMailService; + + private IngestionFlowMailService ingestionFlowMailService; + + private MailParams mailParams; + + @BeforeEach + void init() { + JavaMailSender javaMailSender = new JavaMailSenderImpl(); + mailParams = new MailParams(); + ingestionFlowMailService = new IngestionFlowMailService(asyncSendMailService, mailParams, javaMailSender); + } + + @Test + void sendEmailIngestionSuccess() { + boolean success = true; + String manageFlussoId = "100"; + setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-ok"); + boolean result = ingestionFlowMailService.sendEmail(manageFlussoId, success); + assertTrue(result); + } + + @Test + void sendEmailIngestionError() { + boolean success = false; + String manageFlussoId = "100"; + setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-error"); + boolean result = ingestionFlowMailService.sendEmail(manageFlussoId, success); + assertFalse(result); + } + + void setMailParams(String manageFlussoId, String templatename){ + Long ingestionFlowId = Long.valueOf(manageFlussoId); + IngestionFlowDTO ingestionFlowDTO = new IngestionFlowDTO(); + ingestionFlowDTO.setFileName("test.zip"); + ingestionFlowDTO.setFlowHandlerId(ingestionFlowId); + + HashMap hm = new HashMap<>(); + hm.put("nomeFile", ingestionFlowDTO.getFileName()); + mailParams.setEmailFromAddress("test@test.com"); + mailParams.setEmailFromName("test"); + mailParams.setParams(hm); + mailParams.setTemplateName(templatename); + } + + +} + From 9029b33cd52c2a66d2f44c46a5a3991928c89698 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 09:30:49 +0100 Subject: [PATCH 04/17] fix problems --- .../SendEmailIngestionFlowActivityImpl.java | 64 +++++++++++++++++++ .../service/AsyncSendMailService.java | 1 + .../service/IngestionFlowMailService.java | 6 +- .../helper/MailParameterHelper.java | 29 +++++++++ .../payhub/activities/model/MailParams.java | 2 + .../SendEmailIngestionFlowActivityTest.java | 51 +++++++++------ 6 files changed, 133 insertions(+), 20 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivityImpl.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivityImpl.java new file mode 100644 index 00000000..615ace97 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivityImpl.java @@ -0,0 +1,64 @@ +package it.gov.pagopa.payhub.activities.activity.reportingflow; + +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; +import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; +import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import it.gov.pagopa.payhub.activities.exception.SendMailException; +import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; +import it.gov.pagopa.payhub.activities.model.MailParams; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class SendEmailIngestionFlowActivityImpl implements SendEmailIngestionFlowActivity { + private final IngestionFlowRetrieverService ingestionFlowRetrieverService; + private final AsyncSendMailService asyncSendMailService; + private final MailParams mailParams; + private final JavaMailSender javaMailSender; + private final IngestionFlowDao ingestionFlowDao; + + public SendEmailIngestionFlowActivityImpl(IngestionFlowRetrieverService ingestionFlowRetrieverService, AsyncSendMailService asyncSendMailService, IngestionFlowDao ingestionFlowDao, MailParams mailParams, JavaMailSender javaMailSender) { + this.ingestionFlowRetrieverService = ingestionFlowRetrieverService; + this.asyncSendMailService = asyncSendMailService; + this.ingestionFlowDao = ingestionFlowDao; + this.mailParams = mailParams; + this.javaMailSender = javaMailSender; + } + + /** + * Sends an email based on the process result of the given file ingestionFlow ID. + * + * @param ingestionFlowId the unique identifier of the IngestionFlow record related to the imported file. + * @param success true if the process succeeded, false otherwise. + * @return true if the email was sent successfully, false otherwise. + */ + @Override + public boolean sendEmail(String ingestionFlowId, boolean success) { + // verify if previous operation is success + if (success){ + try { + IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); + if (ingestionFlowDTO!=null) { + mailParams.setIngestionFlowDTO(ingestionFlowDTO); + } + // get e-mail parameters + MailParams params = MailParameterHelper.getMailParams(mailParams); + + // send e-mail if there are no errors in parameters + if (params.isSuccess()){ + mailParams.setHtmlText(params.getHtmlText()); + mailParams.setMailSubject(params.getMailSubject()); + mailParams.setIngestionFlowId(ingestionFlowId); + asyncSendMailService.sendMail(javaMailSender, mailParams); + return true; + } + } catch (Exception e) { + throw new SendMailException("Error sending mail for id: "+ingestionFlowId); + } + } + return false; + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java index b6a3ba35..205d5855 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java @@ -1,5 +1,6 @@ package it.gov.pagopa.payhub.activities.activity.reportingflow.service; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.model.MailParams; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java index 7725dd04..caee8e58 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java @@ -1,5 +1,7 @@ +/* package it.gov.pagopa.payhub.activities.activity.reportingflow.service; + import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.helper.EmailHelper; import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; @@ -47,4 +49,6 @@ public boolean sendEmail(String ingestionFlowId, boolean success){ return false; } -} \ No newline at end of file +} + + */ \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java index 131fdfee..9b4586e6 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java @@ -1,14 +1,38 @@ package it.gov.pagopa.payhub.activities.helper; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.model.MailParams; import org.apache.commons.text.StringSubstitutor; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; public class MailParameterHelper { public static MailParams getMailParams(MailParams mailParams) { + + IngestionFlowDTO ingestionFlowDTO = mailParams.getIngestionFlowDTO(); + + + String fileName = ingestionFlowDTO.getFileName(); + Long fileSize = ingestionFlowDTO.getDownloadedFileSize(); + Long totalRowsNumber = ingestionFlowDTO.getTotalRowsNumber(); + DateFormat parser = new SimpleDateFormat("EEE, MMM dd yyyy, hh:mm:ss"); + String actualDate = parser.format(new Date()); + String mailText = "Il caricamento del file " + fileName; + if (fileSize>0 && totalRowsNumber>0) { + mailText += " è andato a buon fine, tutti i " + totalRowsNumber + " dati presenti sono stati caricati correttamente."; + } + else { + mailText += " NON è andato a buon fine"; + } + try { EmailHelper emailHelper = new EmailHelper(); Properties mailProperties = emailHelper.getProperties(); @@ -23,8 +47,13 @@ public static MailParams getMailParams(MailParams mailParams) { String htmlText = StringSubstitutor.replace(body, mailParams.getParams(), "{", "}"); MailParams params = new MailParams(); + Map map = new HashMap<>(); + map.put("testomail", mailText); + map.put("dataAttuale",actualDate); + map.put("nomeFile", fileName); params.setMailSubject(mailSubject); params.setHtmlText(htmlText); + params.setParams(map); params.setSuccess(true); return params; } diff --git a/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java b/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java index 0e09fd44..3b684185 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/model/MailParams.java @@ -1,5 +1,6 @@ package it.gov.pagopa.payhub.activities.model; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -13,6 +14,7 @@ @NoArgsConstructor @AllArgsConstructor public class MailParams implements Serializable { + IngestionFlowDTO ingestionFlowDTO; Map params; String ingestionFlowId; String emailFromAddress; diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index f2814fbf..406cddbf 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -1,31 +1,27 @@ package it.gov.pagopa.payhub.activities.activity; -import com.sun.jdi.LongValue; +import it.gov.pagopa.payhub.activities.activity.reportingflow.SendEmailIngestionFlowActivityImpl; import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowMailService; import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; -import it.gov.pagopa.payhub.activities.dao.DebtPositionTypeOrgDao; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; -import it.gov.pagopa.payhub.activities.dto.OrganizationDTO; -import it.gov.pagopa.payhub.activities.dto.debtposition.DebtPositionTypeOrgDTO; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; -import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; import it.gov.pagopa.payhub.activities.model.MailParams; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.HashMap; -import java.util.Optional; +import java.util.Map; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class SendEmailIngestionFlowActivityTest { @@ -39,7 +35,7 @@ class SendEmailIngestionFlowActivityTest { @Mock AsyncSendMailService asyncSendMailService; - private IngestionFlowMailService ingestionFlowMailService; + private SendEmailIngestionFlowActivityImpl sendEmailIngestionFlowActivity; private MailParams mailParams; @@ -47,15 +43,15 @@ class SendEmailIngestionFlowActivityTest { void init() { JavaMailSender javaMailSender = new JavaMailSenderImpl(); mailParams = new MailParams(); - ingestionFlowMailService = new IngestionFlowMailService(asyncSendMailService, mailParams, javaMailSender); + sendEmailIngestionFlowActivity = new SendEmailIngestionFlowActivityImpl(ingestionFlowRetrieverService, asyncSendMailService, ingestionFlowDao, mailParams, javaMailSender); } @Test void sendEmailIngestionSuccess() { boolean success = true; String manageFlussoId = "100"; - setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-ok"); - boolean result = ingestionFlowMailService.sendEmail(manageFlussoId, success); + setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-ok", 1000L); + boolean result = sendEmailIngestionFlowActivity.sendEmail(manageFlussoId, success); assertTrue(result); } @@ -63,23 +59,40 @@ void sendEmailIngestionSuccess() { void sendEmailIngestionError() { boolean success = false; String manageFlussoId = "100"; - setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-error"); - boolean result = ingestionFlowMailService.sendEmail(manageFlussoId, success); + setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-error", 0L); + boolean result = sendEmailIngestionFlowActivity.sendEmail(manageFlussoId, success); assertFalse(result); } - void setMailParams(String manageFlussoId, String templatename){ + void setMailParams(String manageFlussoId, String templatename, Long fileSize){ Long ingestionFlowId = Long.valueOf(manageFlussoId); IngestionFlowDTO ingestionFlowDTO = new IngestionFlowDTO(); ingestionFlowDTO.setFileName("test.zip"); ingestionFlowDTO.setFlowHandlerId(ingestionFlowId); + ingestionFlowDTO.setDownloadedFileSize(fileSize); + + DateFormat parser = new SimpleDateFormat("EEE, MMM dd yyyy, hh:mm:ss"); + String actualDate = parser.format(new Date()); + String mailText = "Il caricamento del file " + ingestionFlowDTO.getFileName(); + if (fileSize>0) { + ingestionFlowDTO.setTotalRowsNumber(100L); + mailText += " è andato a buon fine, tutti i " + fileSize + " dati presenti sono stati caricati correttamente."; + } + else { + ingestionFlowDTO.setTotalRowsNumber(0L); + mailText += " NON è andato a buon fine"; + } + + Map map = new HashMap<>(); + map.put("testomail", mailText); + map.put("dataAttuale",actualDate); + map.put("nomeFile", ingestionFlowDTO.getFileName()); - HashMap hm = new HashMap<>(); - hm.put("nomeFile", ingestionFlowDTO.getFileName()); mailParams.setEmailFromAddress("test@test.com"); mailParams.setEmailFromName("test"); - mailParams.setParams(hm); mailParams.setTemplateName(templatename); + mailParams.setParams(map); + mailParams.setIngestionFlowDTO(ingestionFlowDTO); } From e21479f822377875b2282a32a46b1b0597ee5af8 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 09:45:37 +0100 Subject: [PATCH 05/17] delete unused class --- .../service/IngestionFlowMailService.java | 54 ------------------- .../payhub/activities/helper/EmailHelper.java | 2 +- .../helper/MailParameterHelper.java | 5 ++ .../SendEmailIngestionFlowActivityTest.java | 4 +- 4 files changed, 8 insertions(+), 57 deletions(-) delete mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java deleted file mode 100644 index caee8e58..00000000 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowMailService.java +++ /dev/null @@ -1,54 +0,0 @@ -/* -package it.gov.pagopa.payhub.activities.activity.reportingflow.service; - - -import it.gov.pagopa.payhub.activities.exception.SendMailException; -import it.gov.pagopa.payhub.activities.helper.EmailHelper; -import it.gov.pagopa.payhub.activities.helper.MailParameterHelper; -import it.gov.pagopa.payhub.activities.model.MailParams; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.text.StringSubstitutor; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Service; -import org.springframework.util.Assert; - -import java.util.Properties; - -@Service -@Slf4j -public class IngestionFlowMailService { - private final AsyncSendMailService asyncSendMailService; - private final MailParams mailParams; - private final JavaMailSender javaMailSender; - - public IngestionFlowMailService(AsyncSendMailService asyncSendMailService, MailParams mailParams, JavaMailSender javaMailSender) { - this.asyncSendMailService = asyncSendMailService; - this.mailParams = mailParams; - this.javaMailSender = javaMailSender; - } - - public boolean sendEmail(String ingestionFlowId, boolean success){ - // verify if previous operation is success - if (success){ - try { - // get e-mail parameters - MailParams params = MailParameterHelper.getMailParams(mailParams); - - // send e-mail if there are no errors in parameters - if (params.isSuccess()){ - mailParams.setHtmlText(params.getHtmlText()); - mailParams.setMailSubject(params.getMailSubject()); - mailParams.setIngestionFlowId(ingestionFlowId); - asyncSendMailService.sendMail(javaMailSender, mailParams); - return true; - } - } catch (Exception e) { - throw new SendMailException("Error sending mail for id: "+ingestionFlowId); - } - } - return false; - } - -} - - */ \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java index a987db2f..fac1e60b 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java @@ -6,7 +6,7 @@ public class EmailHelper { /** * - * @return Properties + * @return mail template Properties from properties */ public Properties getProperties() { Properties properties = new Properties(); diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java index 9b4586e6..24368baa 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java @@ -15,6 +15,11 @@ import java.util.Properties; public class MailParameterHelper { + /** + * helper for e-mail + * @param mailParams parameters not updated + * @return MailParams parameters updated + */ public static MailParams getMailParams(MailParams mailParams) { IngestionFlowDTO ingestionFlowDTO = mailParams.getIngestionFlowDTO(); diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index 406cddbf..f95f9dda 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -57,11 +57,11 @@ void sendEmailIngestionSuccess() { @Test void sendEmailIngestionError() { - boolean success = false; + boolean success = true; String manageFlussoId = "100"; setMailParams(manageFlussoId, "mail-importFlussoRendicontazione-error", 0L); boolean result = sendEmailIngestionFlowActivity.sendEmail(manageFlussoId, success); - assertFalse(result); + assertTrue(result); } void setMailParams(String manageFlussoId, String templatename, Long fileSize){ From 264df5dc2898b982d8b7cfe872e78c15faa4fd39 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 10:56:01 +0100 Subject: [PATCH 06/17] refactoring mail to send classes --- build.gradle.kts | 4 +-- gradle.lockfile | 1 + .../service/AsyncSendMailService.java | 35 +++++++++++++++++-- .../helper/MailParameterHelper.java | 7 ++-- .../payhub/activities/utils/Constants.java | 7 ++++ src/main/resources/mail-templates.properties | 18 +++++----- .../SendEmailIngestionFlowActivityTest.java | 7 ++-- 7 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/utils/Constants.java diff --git a/build.gradle.kts b/build.gradle.kts index 47ef125d..9a957741 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -71,9 +71,9 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-parameter-names:$jacksonModuleVersion") - // Mail + // Used for mail implementation("org.springframework.boot:spring-boot-starter-mail") - + implementation("org.springframework.retry:spring-retry") implementation("org.jsoup:jsoup:$jsoupVersion") // Testing diff --git a/gradle.lockfile b/gradle.lockfile index e18e69b6..2905cf40 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -44,4 +44,5 @@ org.springframework:spring-context-support:6.1.14=compileClasspath org.jsoup:jsoup:1.18.1=compileClasspath jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath org.springframework.boot:spring-boot-starter-mail:3.3.5=compileClasspath +org.springframework.retry:spring-retry:2.0.10=compileClasspath empty= diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java index 205d5855..a07d2d38 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/AsyncSendMailService.java @@ -1,6 +1,5 @@ package it.gov.pagopa.payhub.activities.activity.reportingflow.service; -import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.model.MailParams; import lombok.extern.slf4j.Slf4j; @@ -9,11 +8,19 @@ import org.jsoup.nodes.Document; import org.jsoup.safety.Safelist; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Recover; +import org.springframework.retry.annotation.Retryable; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; +import java.util.concurrent.Executor; + @Service @Slf4j public class AsyncSendMailService { @@ -24,6 +31,11 @@ public class AsyncSendMailService { @Value("${async.sendMail.queueCapacity:500}") private String queueCapacity; + + @Async("SendMailTaskExecutor") + @Retryable(value = MailException.class, maxAttemptsExpression = "${async.sendMail.retry.maxAttempts}", + backoff = @Backoff(random = true, delayExpression = "${async.sendMail.retry.delay}", + maxDelayExpression = "${async.sendMail.retry.maxDelay}", multiplierExpression = "${async.sendMail.retry.multiplier}")) public void sendMail(JavaMailSender javaMailSender, MailParams mailParams) { try { javaMailSender.send( mimeMessage -> { @@ -35,7 +47,7 @@ public void sendMail(JavaMailSender javaMailSender, MailParams mailParams) { message.setSubject(mailParams.getMailSubject()); String plainText = Jsoup.clean(mailParams.getHtmlText(), "", Safelist.none(), new Document.OutputSettings().prettyPrint(false)); message.setText(plainText, mailParams.getHtmlText()); - log.debug("sending mail message"); + log.info("sending mail message"); } ); log.info("MAIL has been send"); } @@ -44,4 +56,21 @@ public void sendMail(JavaMailSender javaMailSender, MailParams mailParams) { throw new SendMailException("Error in mail sending"); } } + + @Recover + private void recover(MailException e, String[] to, String[] cc, String subject, String htmlText){ + //TODO write fail to db or queue for retry, in case + } + + @Bean("SendMailTaskExecutor") + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(Integer.parseInt(corePoolSize)); + executor.setMaxPoolSize(Integer.parseInt(maxPoolSize)); + executor.setQueueCapacity(Integer.parseInt(queueCapacity)); + executor.setThreadNamePrefix("BatchSendMail-"); + executor.initialize(); + return executor; + } + } diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java index 24368baa..61dd99a4 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java @@ -3,6 +3,7 @@ import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.model.MailParams; +import it.gov.pagopa.payhub.activities.utils.Constants; import org.apache.commons.text.StringSubstitutor; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -53,9 +54,9 @@ public static MailParams getMailParams(MailParams mailParams) { MailParams params = new MailParams(); Map map = new HashMap<>(); - map.put("testomail", mailText); - map.put("dataAttuale",actualDate); - map.put("nomeFile", fileName); + map.put(Constants.MAIL_TEXT, mailText); + map.put(Constants.ACTUAL_DATE,actualDate); + map.put(Constants.FILE_NAME, fileName); params.setMailSubject(mailSubject); params.setHtmlText(htmlText); params.setParams(map); diff --git a/src/main/java/it/gov/pagopa/payhub/activities/utils/Constants.java b/src/main/java/it/gov/pagopa/payhub/activities/utils/Constants.java new file mode 100644 index 00000000..d9fd19c1 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/utils/Constants.java @@ -0,0 +1,7 @@ +package it.gov.pagopa.payhub.activities.utils; + +public class Constants { + public static final String MAIL_TEXT = "mailText"; + public static final String ACTUAL_DATE = "actualDate"; + public static final String FILE_NAME = "fileName"; +} diff --git a/src/main/resources/mail-templates.properties b/src/main/resources/mail-templates.properties index db5c9712..8cf25b58 100644 --- a/src/main/resources/mail-templates.properties +++ b/src/main/resources/mail-templates.properties @@ -1,23 +1,23 @@ -template.mail-importFlussoRendicontazione-ok.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-ok.subject=Rendicontazione: Resoconto Caricamento file: {fileName} template.mail-importFlussoRendicontazione-ok.body= \ Gentile Utente,
\n \ questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ -

Di seguito il testo del messaggio: {testoMail}

\n\n \ -{dataAttuale} +

Di seguito il testo del messaggio: {mailText}

\n\n \ +{actualDate} -template.mail-importFlussoRendicontazione-scarti.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-scarti.subject=Rendicontazione: Resoconto Caricamento file: {fileName} template.mail-importFlussoRendicontazione-scarti.body= \ Gentile Utente,
\n \ questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ -

Di seguito il testo del messaggio: {testoMail}

\n\n \ -{dataAttuale} +

Di seguito il testo del messaggio: {mailText}

\n\n \ +{actualDate} -template.mail-importFlussoRendicontazione-error.subject=Rendicontazione: Resoconto Caricamento file: {nomeFile} +template.mail-importFlussoRendicontazione-error.subject=Rendicontazione: Resoconto Caricamento file: {fileName} template.mail-importFlussoRendicontazione-error.body= \ Gentile Utente,
\n \ questa e' una mail generata in automatico dal sistema MyPay, si raccomanda di non rispondere a questo messaggio.
\n\n \ Contattare l'assistenza per richiedere, se necessario, ulteriori chiarimenti.
\n\n \ -

Di seguito il testo del messaggio: {testoMail}

\n\n \ -{dataAttuale} +

Di seguito il testo del messaggio: {mailText}

\n\n \ +{actualDate} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index f95f9dda..92ffc7a5 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -7,6 +7,7 @@ import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.model.MailParams; +import it.gov.pagopa.payhub.activities.utils.Constants; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -84,9 +85,9 @@ void setMailParams(String manageFlussoId, String templatename, Long fileSize){ } Map map = new HashMap<>(); - map.put("testomail", mailText); - map.put("dataAttuale",actualDate); - map.put("nomeFile", ingestionFlowDTO.getFileName()); + map.put(Constants.MAIL_TEXT, mailText); + map.put(Constants.ACTUAL_DATE,actualDate); + map.put(Constants.FILE_NAME, ingestionFlowDTO.getFileName()); mailParams.setEmailFromAddress("test@test.com"); mailParams.setEmailFromName("test"); From 0d335660f095ec7d90c100bad3ccd2d1b9d4bb23 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 11:11:33 +0100 Subject: [PATCH 07/17] refactoring tests --- .../activity/SendEmailIngestionFlowActivityTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index 92ffc7a5..f65e6a26 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -21,8 +21,10 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class SendEmailIngestionFlowActivityTest { @@ -72,6 +74,9 @@ void setMailParams(String manageFlussoId, String templatename, Long fileSize){ ingestionFlowDTO.setFlowHandlerId(ingestionFlowId); ingestionFlowDTO.setDownloadedFileSize(fileSize); + when(ingestionFlowDao.getIngestionFlow(ingestionFlowId)) + .thenReturn(Optional.of(ingestionFlowDTO)); + DateFormat parser = new SimpleDateFormat("EEE, MMM dd yyyy, hh:mm:ss"); String actualDate = parser.format(new Date()); String mailText = "Il caricamento del file " + ingestionFlowDTO.getFileName(); From 457a180214c3fec072f0cca623ea7c6c74d3f32b Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 11:42:46 +0100 Subject: [PATCH 08/17] refactoring tests --- .../activities/activity/SendEmailIngestionFlowActivityTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index f65e6a26..6b068aaf 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -74,8 +74,10 @@ void setMailParams(String manageFlussoId, String templatename, Long fileSize){ ingestionFlowDTO.setFlowHandlerId(ingestionFlowId); ingestionFlowDTO.setDownloadedFileSize(fileSize); + /* when(ingestionFlowDao.getIngestionFlow(ingestionFlowId)) .thenReturn(Optional.of(ingestionFlowDTO)); + */ DateFormat parser = new SimpleDateFormat("EEE, MMM dd yyyy, hh:mm:ss"); String actualDate = parser.format(new Date()); From 9f58e1f0c553a94434816bdc8e29cccc2438d6f4 Mon Sep 17 00:00:00 2001 From: macacia Date: Wed, 27 Nov 2024 11:58:02 +0100 Subject: [PATCH 09/17] P4ADEV-1545 FdRIngestionActity added service and test --- .../FdRIngestionActivity.java | 2 +- .../FdRIngestionActivityImpl.java | 47 +++++++ .../SendEmailIngestionFlowActivity.java | 2 +- .../UpdateIngestionFlowStatusActivity.java | 2 +- .../service/IngestionFileHandlerService.java | 55 +++++++++ .../IngestionFileValidatorService.java | 71 +++++++++++ .../IngestionFlowRetrieverService.java | 4 +- .../FdRIngestionActivityImpl.java | 63 ---------- .../InvalidIngestionFileException.java | 7 ++ .../payhub/activities/util/AESUtils.java | 116 ++++++++++++++++++ .../payhub/activities/util/FileUtils.java | 50 ++++++++ src/main/resources/application.yml | 9 +- .../IngestionFileHandlerServiceTest.java | 53 ++++++++ .../IngestionFileValidatorServiceTest.java | 29 +++++ .../payhub/activities/util/AESUtilsTest.java | 47 +++++++ .../payhub/activities/util/FileUtilsTest.java | 65 ++++++++++ 16 files changed, 553 insertions(+), 69 deletions(-) rename src/main/java/it/gov/pagopa/payhub/activities/activity/{reportingflow => paymentsreporting}/FdRIngestionActivity.java (89%) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java rename src/main/java/it/gov/pagopa/payhub/activities/activity/{reportingflow => paymentsreporting}/SendEmailIngestionFlowActivity.java (90%) rename src/main/java/it/gov/pagopa/payhub/activities/activity/{reportingflow => paymentsreporting}/UpdateIngestionFlowStatusActivity.java (88%) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerService.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorService.java rename src/main/java/it/gov/pagopa/payhub/activities/activity/{reportingflow => paymentsreporting}/service/IngestionFlowRetrieverService.java (85%) delete mode 100644 src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/exception/InvalidIngestionFileException.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/util/AESUtilsTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/util/FileUtilsTest.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivity.java similarity index 89% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivity.java index 3a5d17bf..88e082e5 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivity.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; /** diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java new file mode 100644 index 00000000..76d4cfce --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java @@ -0,0 +1,47 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; + +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileHandlerService; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileValidatorService; +import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Component +public class FdRIngestionActivityImpl implements FdRIngestionActivity { + private final IngestionFlowRetrieverService ingestionFlowRetrieverService; + private final IngestionFileValidatorService ingestionFileValidatorService; + private final IngestionFileHandlerService ingestionFileHandlerService; + + public FdRIngestionActivityImpl(IngestionFlowRetrieverService ingestionFlowRetrieverService, + IngestionFileValidatorService ingestionFileValidatorService, + IngestionFileHandlerService ingestionFileHandlerService) { + this.ingestionFlowRetrieverService = ingestionFlowRetrieverService; + this.ingestionFileValidatorService = ingestionFileValidatorService; + this.ingestionFileHandlerService = ingestionFileHandlerService; + } + + @Override + public FdRIngestionActivityResult processFile(String ingestionFlowId) { + List iufList = new ArrayList<>(); + boolean success = true; + + try { + IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getIngestionFlow(Long.valueOf(ingestionFlowId)); + + ingestionFileValidatorService.validate(ingestionFlowDTO.getFilePathName(), ingestionFlowDTO.getFileName(), ingestionFlowDTO.getRequestTokenCode()); + + ingestionFileHandlerService.setUpProcess(ingestionFlowDTO.getFilePathName(), ingestionFlowDTO.getFileName()); + } catch (Exception e) { + log.error("Error during IngestionActivity flowId {} due to: {}", ingestionFlowId, e.getMessage()); + success = false; + } finally { + return new FdRIngestionActivityResult(iufList, success); + } + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivity.java similarity index 90% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivity.java index 7a8c94f7..41520dc8 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/SendEmailIngestionFlowActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivity.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; /** * Interface for SendEmailIngestionFlowActivity. diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/UpdateIngestionFlowStatusActivity.java similarity index 88% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/UpdateIngestionFlowStatusActivity.java index 5c3f0856..7c7a5359 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/UpdateIngestionFlowStatusActivity.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/UpdateIngestionFlowStatusActivity.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; /** * Interface for the UpdateIngestionFlowStatusActivity. diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerService.java new file mode 100644 index 00000000..0c73d087 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerService.java @@ -0,0 +1,55 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; + +import it.gov.pagopa.payhub.activities.util.AESUtils; +import it.gov.pagopa.payhub.activities.util.FileUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Slf4j +@Service +public class IngestionFileHandlerService { + private static final String TEMPORARY_PATH = "TEMP"; + + private final String dataCipherPsw; + + public IngestionFileHandlerService(@Value("${data-cipher.encrypt-psw}") String dataCipherPsw) { + this.dataCipherPsw = dataCipherPsw; + } + + public Path setUpProcess(String relativePath, String filename) throws IOException { + Path relativePathDir = Paths.get(relativePath); + Path encryptedFilePath = relativePathDir.resolve(filename); + + // Prepare temporary path + Path temporaryPath = relativePathDir.resolve(TEMPORARY_PATH); + Files.createDirectories(temporaryPath); + + // Derive the decrypted file name and path + String filenameNoCipher = filename.replace(AESUtils.CIPHER_EXTENSION, ""); + Path temporaryZipFilePath = temporaryPath.resolve(filenameNoCipher); + + // Decrypt the file + log.debug("Decrypting file: {}", encryptedFilePath); + AESUtils.decrypt(dataCipherPsw, encryptedFilePath.toFile(), temporaryZipFilePath.toFile()); + + // Validate ZIP file + log.debug("Validating ZIP file: {}", temporaryZipFilePath); + FileUtils.validateZip(temporaryZipFilePath); + + // Unzip the file + String unzippedFilename = filenameNoCipher.replace(".zip", ".xml"); + Path outputUnzippedPath = temporaryPath.resolve(unzippedFilename); + + log.debug("Unzipping file: {} to {}", temporaryZipFilePath, outputUnzippedPath); + FileUtils.unzipFile(temporaryZipFilePath, outputUnzippedPath); + + log.debug("File setup process completed successfully for: {}", filename); + return outputUnzippedPath; + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorService.java new file mode 100644 index 00000000..4753cd8f --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorService.java @@ -0,0 +1,71 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; + +import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.io.IOUtils; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +@Slf4j +@Service +public class IngestionFileValidatorService { + + public void validate(String relativePath, String filename, String requestTokenCode) { + Path fileLocation = Paths.get(relativePath, filename); + + validateFile(fileLocation); + validateAUTH(fileLocation.toString(), requestTokenCode); + validateMD5(fileLocation.toString()); + } + + private void validateFile(Path filePath) { + if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) { + throw new InvalidIngestionFileException("File non trovato: " + filePath); + } + } + + private void validateMD5(String filename) { + String md5 = filename.replace(".zip", ".md5"); + String valueMD5 = readContentFile(md5); + String calculatedMD5 = calculateMd5(filename); + if(!valueMD5.equalsIgnoreCase(calculatedMD5)) { + throw new InvalidIngestionFileException("Error while calculating MD5 file value"); + } + } + + private void validateAUTH(String filename, String requestToken) { + String auth = filename.replace(".zip", ".auth"); + String valueAUTH = readContentFile(auth); + if(!valueAUTH.equalsIgnoreCase(requestToken)) { + throw new InvalidIngestionFileException("Error while calculating MD5 file value"); + } + } + + private String readContentFile(String filename) { + try { + return Files.readString(Paths.get(filename)); + } catch (IOException e) { + throw new InvalidIngestionFileException("Error while reading file: " + filename); + } + } + + private String calculateMd5(String filename) { + try (InputStream is = Files.newInputStream(Paths.get(filename))) { + MessageDigest md = MessageDigest.getInstance("MD5"); + DigestInputStream dis = new DigestInputStream(is, md); + IOUtils.toByteArray(dis); + return Hex.encodeHexString(md.digest()); + } catch (NoSuchAlgorithmException | IOException e) { + throw new InvalidIngestionFileException("Error while calculating MD5"); + } + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverService.java similarity index 85% rename from src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java rename to src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverService.java index e443cb59..6cca2811 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/service/IngestionFlowRetrieverService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverService.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow.service; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; @@ -18,7 +18,7 @@ public IngestionFlowRetrieverService(IngestionFlowDao ingestionFlowDao) { this.ingestionFlowDao = ingestionFlowDao; } - public IngestionFlowDTO getByFlowId(Long ingestionFlowId) { + public IngestionFlowDTO getIngestionFlow(Long ingestionFlowId) { Optional ingestionFlow = ingestionFlowDao.getIngestionFlow(ingestionFlowId); return ingestionFlow diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java deleted file mode 100644 index 1152c3a6..00000000 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/reportingflow/FdRIngestionActivityImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow; - -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; -import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; -import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -@Slf4j -@Component -public class FdRIngestionActivityImpl implements FdRIngestionActivity { - private final IngestionFlowRetrieverService ingestionFlowRetrieverService; - - public FdRIngestionActivityImpl(IngestionFlowRetrieverService ingestionFlowRetrieverService) { - this.ingestionFlowRetrieverService = ingestionFlowRetrieverService; - } - - @Override - public FdRIngestionActivityResult processFile(String ingestionFlowId) { - List iufList = new ArrayList<>(); - boolean success = true; - - try { - IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); - // Creazione directory temporanea - - // Validazione file - - - // Decifratura - - - // Controllo sicurezza zip - - - // Unzip - - - // Validazione XSD e unmarshalling - - - // Lettura e processazione file - - - // Sposta file in archivio - - } catch (Exception e) { - log.error("Error during IngestionActivity flowId {} due to: {}", ingestionFlowId, e.getMessage()); - success = false; - - // Sposta file nella directory di errore - } finally { - // Pulizia directory temporanea - - - return new FdRIngestionActivityResult(iufList, success); - } - - } -} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/exception/InvalidIngestionFileException.java b/src/main/java/it/gov/pagopa/payhub/activities/exception/InvalidIngestionFileException.java new file mode 100644 index 00000000..f8bf1a9b --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/exception/InvalidIngestionFileException.java @@ -0,0 +1,7 @@ +package it.gov.pagopa.payhub.activities.exception; + +public class InvalidIngestionFileException extends ActivitiesException { + public InvalidIngestionFileException(String message) { + super(message); + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java new file mode 100644 index 00000000..15515828 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java @@ -0,0 +1,116 @@ +package it.gov.pagopa.payhub.activities.util; + +import javax.crypto.*; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +public class AESUtils { + private AESUtils() { + } + + private static final String ALGORITHM = "AES/GCM/NoPadding"; + private static final String FACTORY_INSTANCE = "PBKDF2WithHmacSHA256"; + private static final int TAG_LENGTH_BIT = 128; + private static final int IV_LENGTH_BYTE = 12; + private static final int SALT_LENGTH_BYTE = 16; + private static final String ALGORITHM_TYPE = "AES"; + private static final int KEY_LENGTH = 256; + private static final int ITERATION_COUNT = 65536; + + public static final String CIPHER_EXTENSION = ".cipher"; + + public static byte[] getRandomNonce(int length) { + byte[] nonce = new byte[length]; + new SecureRandom().nextBytes(nonce); + return nonce; + } + + public static SecretKey getSecretKey(String password, byte[] salt) { + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH); + + try { + SecretKeyFactory factory = SecretKeyFactory.getInstance(FACTORY_INSTANCE); + return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), ALGORITHM_TYPE); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new IllegalStateException("Cannot initialize cryptographic data", e); + } + } + + public static InputStream encrypt(String password, InputStream plainStream) { + byte[] salt = getRandomNonce(SALT_LENGTH_BYTE); + SecretKey secretKey = getSecretKey(password, salt); + + // GCM recommends 12 bytes iv + byte[] iv = getRandomNonce(IV_LENGTH_BYTE); + Cipher cipher = initCipher(Cipher.ENCRYPT_MODE, secretKey, iv); + + // prefix IV and Salt to cipher text + byte[] prefix = ByteBuffer.allocate(iv.length + salt.length) + .put(iv) + .put(salt) + .array(); + + return new SequenceInputStream( + new ByteArrayInputStream(prefix), + new CipherInputStream(new BufferedInputStream(plainStream), cipher)); + } + + public static File encrypt(String password, File plainFile) { + File cipherFile = new File(plainFile.getAbsolutePath() + CIPHER_EXTENSION); + try(FileInputStream fis = new FileInputStream(plainFile); + InputStream cipherStream = encrypt(password, fis)){ + Files.copy(cipherStream, cipherFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new IllegalStateException("Something went wrong when ciphering input file " + plainFile.getAbsolutePath(), e); + } + return cipherFile; + } + + public static InputStream decrypt(String password, InputStream cipherStream) { + try { + byte[] iv = cipherStream.readNBytes(IV_LENGTH_BYTE); + byte[] salt = cipherStream.readNBytes(SALT_LENGTH_BYTE); + + SecretKey secretKey = getSecretKey(password, salt); + Cipher cipher = initCipher(Cipher.DECRYPT_MODE, secretKey, iv); + + return new CipherInputStream(new BufferedInputStream(cipherStream), cipher); + } catch (IOException e) { + throw new IllegalStateException("Cannot read AES prefix data", e); + } + } + + public static void decrypt(String password, File cipherFile, File outputPlainFile) { + try(FileInputStream fis = new FileInputStream(cipherFile); + InputStream plainStream = decrypt(password, fis)){ + Files.copy(plainStream, outputPlainFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new IllegalStateException("Something went wrong when deciphering input file " + cipherFile.getAbsolutePath(), e); + } + } + + private static Cipher initCipher(int mode, SecretKey secretKey, byte[] iv) { + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(mode, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); + return cipher; + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException + | InvalidAlgorithmParameterException e) { + throw new IllegalStateException("Cannot initialize cipher data", e); + } + } + +} diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java new file mode 100644 index 00000000..e786ec7b --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java @@ -0,0 +1,50 @@ +package it.gov.pagopa.payhub.activities.util; + +import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class FileUtils { + + public FileUtils() {} + + public static void validateZip(Path zipFilePath) { + try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) { + zipFile.entries(); + } catch (Exception e) { + throw new InvalidIngestionFileException("Invalid zip file"); + } + } + + public static Path unzipFile(Path zipFilePath, Path outputDir) { + Path extractedFilePath; + try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) { + Enumeration entries = zipFile.entries(); + if (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.isDirectory()) { + throw new InvalidIngestionFileException("ZIP file contains directories, but only files are expected"); + } + Path entryPath = outputDir.resolve(entry.getName()); + Files.createDirectories(entryPath.getParent()); + try { + Files.copy(zipFile.getInputStream(entry), entryPath, StandardCopyOption.REPLACE_EXISTING); + extractedFilePath = entryPath; // Restituisci il path completo del file estratto + } catch (IOException e) { + throw new InvalidIngestionFileException("Failed to extract file: " + entry.getName()); + } + } else { + throw new InvalidIngestionFileException("ZIP file is empty or contains no files"); + } + } catch (IOException e) { + throw new InvalidIngestionFileException("Error while unzipping file: " + zipFilePath); + } + return extractedFilePath; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f98de691..8c0ec9f1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,11 @@ spring: application: name: ${artifactId} - version: ${version} \ No newline at end of file + version: ${version} + +data-chiper: + encrypt-psw: "\${DATA_CIPHER_ENCRYPT_PASSWORD:PWD}" + + +ingestion-flow: + destination-base-path: "" \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java new file mode 100644 index 00000000..695f6def --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java @@ -0,0 +1,53 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; + +import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; +import it.gov.pagopa.payhub.activities.util.AESUtils; +import it.gov.pagopa.payhub.activities.util.FileUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class IngestionFileHandlerServiceTest { + + private static final String TEST_PATH = "some/path"; + private static final String TEST_FILENAME = "testFile.zip"; + private static final String TEST_CIPHER_PSW = "testPassword"; + + private IngestionFileHandlerService ingestionFileHandlerService; + + + @BeforeEach + void setUp() { + ingestionFileHandlerService = new IngestionFileHandlerService(TEST_CIPHER_PSW); + } + + @Test + void setUpProcessSuccess() throws IOException { + + } + + @Test + void decryptFailed() throws IOException { + + } + + @Test + void validateZipFailed() throws IOException { + + } + + @Test + void unzipFileFailed() throws IOException { + + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java new file mode 100644 index 00000000..363d218a --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java @@ -0,0 +1,29 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; + +import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; +import org.junit.jupiter.api.*; +import org.mockito.*; + +import java.nio.file.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class IngestionFileValidatorServiceTest { + + @Mock + private Path filePath; + @Mock + private Path md5FilePath; + @Mock + private Path authFilePath; + + @InjectMocks + private IngestionFileValidatorService ingestionFileValidatorService; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + +} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/util/AESUtilsTest.java b/src/test/java/it/gov/pagopa/payhub/activities/util/AESUtilsTest.java new file mode 100644 index 00000000..ad2ee196 --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/util/AESUtilsTest.java @@ -0,0 +1,47 @@ +package it.gov.pagopa.payhub.activities.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +class AESUtilsTest { + + @Test + void testStream() throws IOException { + // Given + String plain = "PLAINTEXT"; + String psw = "PSW"; + + // When + InputStream cipherStream = AESUtils.encrypt(psw, new ByteArrayInputStream(plain.getBytes(StandardCharsets.UTF_8))); + InputStream resultStream = AESUtils.decrypt(psw, cipherStream); + + // Then + Assertions.assertEquals(new String(resultStream.readAllBytes(), StandardCharsets.UTF_8), plain); + } + + @Test + void testFile() throws IOException { + // Given + String plain = "PLAINTEXT"; + Path plainFile = Path.of("build", "tmp", "plainFile.txt"); + Files.writeString(plainFile, plain); + String psw = "PSW"; + Path decryptedFile = plainFile.getParent().resolve("decryptedFile.txt"); + + // When + File cipherFile = AESUtils.encrypt(psw, plainFile.toFile()); + AESUtils.decrypt(psw, cipherFile, decryptedFile.toFile()); + + // Then + Assertions.assertEquals(Files.readAllLines(decryptedFile), List.of(plain)); + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/util/FileUtilsTest.java b/src/test/java/it/gov/pagopa/payhub/activities/util/FileUtilsTest.java new file mode 100644 index 00000000..fec48dfa --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/util/FileUtilsTest.java @@ -0,0 +1,65 @@ +package it.gov.pagopa.payhub.activities.util; + +import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import static org.junit.jupiter.api.Assertions.*; + +public class FileUtilsTest { + + private Path zipPath; + private Path outputDir; + + @BeforeEach + public void setUp() throws Exception { + zipPath = Files.createTempFile("testZip", ".zip"); + outputDir = Files.createTempDirectory("output"); + + // Crea un file ZIP di test + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipPath))) { + ZipEntry entry = new ZipEntry("testFile.xml"); + zos.putNextEntry(entry); + zos.write("This is a test file".getBytes()); + zos.closeEntry(); + } + } + + @AfterEach + public void tearDown() throws Exception { + // Pulisce i file temporanei + Files.deleteIfExists(zipPath); + Files.walk(outputDir) + .map(Path::toFile) + .forEach(file -> file.delete()); + } + + @Test + public void testValidateZip_doesNotThrowExceptionWhenValid(){ + assertDoesNotThrow(() -> FileUtils.validateZip(zipPath)); + } + + @Test + public void testValidateZip_throwsExceptionWhenInvalid() throws Exception { + + Path invalidZipPath = Files.createTempFile("invalidZip", ".zip"); + + assertThrows(InvalidIngestionFileException.class, () -> FileUtils.validateZip(invalidZipPath)); + + Files.deleteIfExists(invalidZipPath); + } + + @Test + public void testUnzipFile_extractsFileSuccessfully() { + Path result = FileUtils.unzipFile(zipPath, outputDir); + + Path expectedFilePath = outputDir.resolve("testFile.xml"); + assertEquals(expectedFilePath, result, "Returned path should match the extracted file path"); + } +} From 05cde127464674c6f45d07a55bb44e4c6e88f2fa Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 12:27:20 +0100 Subject: [PATCH 10/17] refactoring classes --- .../SendEmailIngestionFlowActivityImpl.java | 6 +++--- .../activity/SendEmailIngestionFlowActivityTest.java | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java index 615ace97..1a8dccf8 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java @@ -1,7 +1,7 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; @@ -40,7 +40,7 @@ public boolean sendEmail(String ingestionFlowId, boolean success) { // verify if previous operation is success if (success){ try { - IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getByFlowId(Long.valueOf(ingestionFlowId)); + IngestionFlowDTO ingestionFlowDTO = ingestionFlowRetrieverService.getIngestionFlow(Long.valueOf(ingestionFlowId)); if (ingestionFlowDTO!=null) { mailParams.setIngestionFlowDTO(ingestionFlowDTO); } diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index 6b068aaf..79a96740 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -1,8 +1,8 @@ package it.gov.pagopa.payhub.activities.activity; -import it.gov.pagopa.payhub.activities.activity.reportingflow.SendEmailIngestionFlowActivityImpl; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.SendEmailIngestionFlowActivityImpl; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; @@ -21,10 +21,8 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class SendEmailIngestionFlowActivityTest { From 93450f81b61e56a6fe14d02a95571f4abc9fc7b1 Mon Sep 17 00:00:00 2001 From: macacia Date: Wed, 27 Nov 2024 12:38:27 +0100 Subject: [PATCH 11/17] P4ADEV-1545 FdRIngestionActity added utils and its test --- .../payhub/activities/util/FileUtils.java | 1 + .../activities/util/SecureFileUtils.java | 26 ++++++++++++++ .../activities/util/SecureFileUtilsTest.java | 34 +++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/util/SecureFileUtilsTest.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java index e786ec7b..bd7e8370 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java @@ -28,6 +28,7 @@ public static Path unzipFile(Path zipFilePath, Path outputDir) { Enumeration entries = zipFile.entries(); if (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); + SecureFileUtils.checkFileName(entry); if (entry.isDirectory()) { throw new InvalidIngestionFileException("ZIP file contains directories, but only files are expected"); } diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java new file mode 100644 index 00000000..ca21f631 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java @@ -0,0 +1,26 @@ +package it.gov.pagopa.payhub.activities.util; + +import java.util.zip.ZipEntry; + +public class SecureFileUtils { + /** + * Checks if the name of the zip entry is safe. + * The name must: + * - Start with an alphanumeric character. + * - Not contain the string "..". + * @param fileName The name of the zip entry. + * @return fileName if the name is safe. + */ + public static String checkFileName(String fileName) throws IllegalArgumentException { + if (!Character.isLetterOrDigit(fileName.charAt(0)) + || fileName.contains("..")) { + throw new IllegalArgumentException("Potential Zip Slip exploit detected: " + fileName); + } + return fileName; + } + + public static ZipEntry checkFileName(ZipEntry entry) throws IllegalArgumentException { + checkFileName(entry.getName()); + return entry; + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/activities/util/SecureFileUtilsTest.java b/src/test/java/it/gov/pagopa/payhub/activities/util/SecureFileUtilsTest.java new file mode 100644 index 00000000..594c7abc --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/util/SecureFileUtilsTest.java @@ -0,0 +1,34 @@ +package it.gov.pagopa.payhub.activities.util; + +import org.junit.jupiter.api.Test; + +import java.util.zip.ZipEntry; + +import static org.junit.jupiter.api.Assertions.*; + +class SecureFileUtilsTest { + + @Test + void givenValidFileNameThenOk() throws IllegalArgumentException { + String validFileName = "safeFile.txt"; + assertDoesNotThrow(() -> SecureFileUtils.checkFileName(validFileName)); + } + + @Test + void givenInvalidFileNameStartingWithNonAlphanumericThenException() { + String invalidFileName = "/unsafeFile.txt"; + assertThrows(IllegalArgumentException.class, () -> SecureFileUtils.checkFileName(invalidFileName)); + } + + @Test + void givenInvalidFileNameContainingDotDotThenException() { + String invalidFileName = "safe/../../unsafeFile.txt"; + assertThrows(IllegalArgumentException.class, () -> SecureFileUtils.checkFileName(invalidFileName)); + } + + @Test + void givenValidZipEntryThenReturnZipEntry() throws IllegalArgumentException { + ZipEntry validEntry = new ZipEntry("safeFile.txt"); + assertEquals(validEntry, SecureFileUtils.checkFileName(validEntry)); + } +} \ No newline at end of file From 9780f00dde76e24317f48c5d7ad4bb14b3b7e808 Mon Sep 17 00:00:00 2001 From: macacia Date: Wed, 27 Nov 2024 12:48:24 +0100 Subject: [PATCH 12/17] P4ADEV-1545 FdRIngestionActity fix --- .../java/it/gov/pagopa/payhub/activities/util/FileUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java index bd7e8370..3caf287d 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java @@ -28,11 +28,11 @@ public static Path unzipFile(Path zipFilePath, Path outputDir) { Enumeration entries = zipFile.entries(); if (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); - SecureFileUtils.checkFileName(entry); if (entry.isDirectory()) { throw new InvalidIngestionFileException("ZIP file contains directories, but only files are expected"); } - Path entryPath = outputDir.resolve(entry.getName()); + String checkedFilename = SecureFileUtils.checkFileName(entry.getName()); + Path entryPath = outputDir.resolve(checkedFilename); Files.createDirectories(entryPath.getParent()); try { Files.copy(zipFile.getInputStream(entry), entryPath, StandardCopyOption.REPLACE_EXISTING); From a5d451dd1c9de44a0bf8c9295f048da16f493ed7 Mon Sep 17 00:00:00 2001 From: macacia Date: Wed, 27 Nov 2024 13:30:12 +0100 Subject: [PATCH 13/17] P4ADEV-1545 FdRIngestionActity fix --- .../FdRIngestionActivityImpl.java | 5 +- .../dto/reportingflow/IngestionFlowDTO.java | 2 +- .../payhub/activities/util/AESUtils.java | 2 - .../payhub/activities/util/FileUtils.java | 3 +- .../activities/util/SecureFileUtils.java | 3 ++ ...peratorOnDebtPositionTypeActivityTest.java | 3 +- .../FdRIngestionActivityImplTest.java | 29 +++++++++++ .../IngestionFileHandlerServiceTest.java | 9 ---- .../IngestionFileValidatorServiceTest.java | 11 ++-- .../IngestionFlowRetrieverServiceTest.java | 51 +++++++++++++++++++ 10 files changed, 94 insertions(+), 24 deletions(-) rename src/test/java/it/gov/pagopa/payhub/activities/activity/{ => debtposition}/AuthorizeOperatorOnDebtPositionTypeActivityTest.java (94%) create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImplTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverServiceTest.java diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java index 76d4cfce..894d9f87 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImpl.java @@ -1,8 +1,8 @@ package it.gov.pagopa.payhub.activities.activity.paymentsreporting; import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileHandlerService; -import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileValidatorService; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; import it.gov.pagopa.payhub.activities.dto.reportingflow.FdRIngestionActivityResult; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import lombok.extern.slf4j.Slf4j; @@ -40,8 +40,7 @@ public FdRIngestionActivityResult processFile(String ingestionFlowId) { } catch (Exception e) { log.error("Error during IngestionActivity flowId {} due to: {}", ingestionFlowId, e.getMessage()); success = false; - } finally { - return new FdRIngestionActivityResult(iufList, success); } + return new FdRIngestionActivityResult(iufList, success); } } diff --git a/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java index 7d4502db..e79a85ac 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/dto/reportingflow/IngestionFlowDTO.java @@ -13,7 +13,7 @@ @NoArgsConstructor @AllArgsConstructor public class IngestionFlowDTO { - private Long flowHandlerId; + private Long ingestionFlowId; private int version; private OrganizationDTO orgId; private String PspIdentifier; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java index 15515828..94cd1262 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/AESUtils.java @@ -6,8 +6,6 @@ import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.security.InvalidAlgorithmParameterException; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java index 3caf287d..7c01b9d0 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/FileUtils.java @@ -12,7 +12,8 @@ public class FileUtils { - public FileUtils() {} + private FileUtils() { + } public static void validateZip(Path zipFilePath) { try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) { diff --git a/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java b/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java index ca21f631..9ebea02f 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/util/SecureFileUtils.java @@ -3,6 +3,9 @@ import java.util.zip.ZipEntry; public class SecureFileUtils { + private SecureFileUtils() { + } + /** * Checks if the name of the zip entry is safe. * The name must: diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/AuthorizeOperatorOnDebtPositionTypeActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/debtposition/AuthorizeOperatorOnDebtPositionTypeActivityTest.java similarity index 94% rename from src/test/java/it/gov/pagopa/payhub/activities/activity/AuthorizeOperatorOnDebtPositionTypeActivityTest.java rename to src/test/java/it/gov/pagopa/payhub/activities/activity/debtposition/AuthorizeOperatorOnDebtPositionTypeActivityTest.java index 260addbc..a25591d7 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/AuthorizeOperatorOnDebtPositionTypeActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/debtposition/AuthorizeOperatorOnDebtPositionTypeActivityTest.java @@ -1,6 +1,5 @@ -package it.gov.pagopa.payhub.activities.activity; +package it.gov.pagopa.payhub.activities.activity.debtposition; -import it.gov.pagopa.payhub.activities.activity.debtposition.AuthorizeOperatorOnDebtPositionTypeActivity; import it.gov.pagopa.payhub.activities.dao.DebtPositionTypeOrgDao; import it.gov.pagopa.payhub.activities.dto.OrganizationDTO; import it.gov.pagopa.payhub.activities.dto.debtposition.DebtPositionTypeOrgDTO; diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImplTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImplTest.java new file mode 100644 index 00000000..5758443b --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/FdRIngestionActivityImplTest.java @@ -0,0 +1,29 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting; + +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileHandlerService; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFileValidatorService; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class FdRIngestionActivityImplTest { + + @Mock + private IngestionFlowRetrieverService ingestionFlowRetrieverServiceMock; + @Mock + private IngestionFileValidatorService ingestionFileValidatorServiceMock; + @Mock + private IngestionFileHandlerService ingestionFileHandlerServiceMock; + + private FdRIngestionActivityImpl activity; + + @BeforeEach + void init() { + activity = new FdRIngestionActivityImpl(ingestionFlowRetrieverServiceMock, ingestionFileValidatorServiceMock, ingestionFileHandlerServiceMock); + } + + +} \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java index 695f6def..0acfae37 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileHandlerServiceTest.java @@ -1,20 +1,11 @@ package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; -import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; -import it.gov.pagopa.payhub.activities.util.AESUtils; -import it.gov.pagopa.payhub.activities.util.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.*; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.File; import java.io.IOException; -import java.nio.file.*; - -import static org.mockito.Mockito.*; -import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class IngestionFileHandlerServiceTest { diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java index 363d218a..b4149a15 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFileValidatorServiceTest.java @@ -1,12 +1,11 @@ package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; -import it.gov.pagopa.payhub.activities.exception.InvalidIngestionFileException; -import org.junit.jupiter.api.*; -import org.mockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; -import java.nio.file.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import java.nio.file.Path; class IngestionFileValidatorServiceTest { diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverServiceTest.java new file mode 100644 index 00000000..b60a2fd1 --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/IngestionFlowRetrieverServiceTest.java @@ -0,0 +1,51 @@ +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; + +import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; +import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; +import it.gov.pagopa.payhub.activities.exception.IngestionFlowNotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class IngestionFlowRetrieverServiceTest { + + @Mock + private IngestionFlowDao ingestionFlowDaoMock; + + private IngestionFlowRetrieverService service; + + @BeforeEach + void init() { + service = new IngestionFlowRetrieverService(ingestionFlowDaoMock); + } + + @Test + void givenIngestionFlowIdThenSuccess() { + Long ingestionFlowId = 1L; + IngestionFlowDTO expected = IngestionFlowDTO.builder() + .ingestionFlowId(ingestionFlowId) + .build(); + + when(ingestionFlowDaoMock.getIngestionFlow(ingestionFlowId)).thenReturn(Optional.of(expected)); + + IngestionFlowDTO actual = service.getIngestionFlow(ingestionFlowId); + + assertEquals(expected, actual); + } + + @Test + void givenIngestionFlowIdThenThrowIngestionFlowNotFoundException() { + Long ingestionFlowId = 1L; + when(ingestionFlowDaoMock.getIngestionFlow(ingestionFlowId)).thenReturn(Optional.empty()); + assertThrows(IngestionFlowNotFoundException.class, () -> service.getIngestionFlow(ingestionFlowId)); + } +} \ No newline at end of file From 6c672f270585b8c82733cff0f0113cff6ce97dc6 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 13:58:24 +0100 Subject: [PATCH 14/17] modify changed field in used class --- .../activities/activity/SendEmailIngestionFlowActivityTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index 79a96740..f2b0755e 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -69,7 +69,7 @@ void setMailParams(String manageFlussoId, String templatename, Long fileSize){ Long ingestionFlowId = Long.valueOf(manageFlussoId); IngestionFlowDTO ingestionFlowDTO = new IngestionFlowDTO(); ingestionFlowDTO.setFileName("test.zip"); - ingestionFlowDTO.setFlowHandlerId(ingestionFlowId); + ingestionFlowDTO.setIngestionFlowId(ingestionFlowId); ingestionFlowDTO.setDownloadedFileSize(fileSize); /* From 7a318ff5b1c86f178c3dee3e97adb68cd9ca4e90 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 14:49:40 +0100 Subject: [PATCH 15/17] bug fixing --- .../paymentsreporting/SendEmailIngestionFlowActivityImpl.java | 2 +- .../paymentsreporting/service/AsyncSendMailService.java | 2 +- .../activities/activity/SendEmailIngestionFlowActivityTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java index 1a8dccf8..002652eb 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/SendEmailIngestionFlowActivityImpl.java @@ -1,7 +1,7 @@ package it.gov.pagopa.payhub.activities.activity.paymentsreporting; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.AsyncSendMailService; import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; import it.gov.pagopa.payhub.activities.exception.SendMailException; diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java index a07d2d38..59120c98 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.payhub.activities.activity.reportingflow.service; +package it.gov.pagopa.payhub.activities.activity.paymentsreporting.service; import it.gov.pagopa.payhub.activities.exception.SendMailException; import it.gov.pagopa.payhub.activities.model.MailParams; diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index f2b0755e..81817aba 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -1,8 +1,8 @@ package it.gov.pagopa.payhub.activities.activity; import it.gov.pagopa.payhub.activities.activity.paymentsreporting.SendEmailIngestionFlowActivityImpl; +import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.AsyncSendMailService; import it.gov.pagopa.payhub.activities.activity.paymentsreporting.service.IngestionFlowRetrieverService; -import it.gov.pagopa.payhub.activities.activity.reportingflow.service.AsyncSendMailService; import it.gov.pagopa.payhub.activities.dao.IngestionFlowDao; import it.gov.pagopa.payhub.activities.dto.reportingflow.IngestionFlowDTO; From 2c8492b6761c27473985e9cfe8245fa2704e77f2 Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 15:01:31 +0100 Subject: [PATCH 16/17] code review --- .../it/gov/pagopa/payhub/activities/helper/EmailHelper.java | 4 +++- .../payhub/activities/helper/MailParameterHelper.java | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java index fac1e60b..a5d1523f 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/EmailHelper.java @@ -1,5 +1,7 @@ package it.gov.pagopa.payhub.activities.helper; +import it.gov.pagopa.payhub.activities.exception.SendMailException; + import java.io.InputStream; import java.util.Properties; @@ -14,7 +16,7 @@ public Properties getProperties() { InputStream inputStream = EmailHelper.class.getClassLoader().getResourceAsStream("mail-templates.properties"); properties.load(inputStream); } catch (Exception e) { - return null; + throw new SendMailException("Error in mail template configuration"); } return properties; } diff --git a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java index 61dd99a4..2393fd4e 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/helper/MailParameterHelper.java @@ -6,7 +6,6 @@ import it.gov.pagopa.payhub.activities.utils.Constants; import org.apache.commons.text.StringSubstitutor; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -63,8 +62,11 @@ public static MailParams getMailParams(MailParams mailParams) { params.setSuccess(true); return params; } + catch (SendMailException sendMailException) { + throw sendMailException; + } catch (Exception e) { - throw new SendMailException("Error in mail configuration"); + throw new SendMailException("Error in mail parameters"); } } } From 14fe817baae5dc65085076a4989bb3cfadb64f8b Mon Sep 17 00:00:00 2001 From: Silvano Tamburini Date: Wed, 27 Nov 2024 15:26:55 +0100 Subject: [PATCH 17/17] remove unused code --- .../paymentsreporting/service/AsyncSendMailService.java | 4 ++-- .../activity/SendEmailIngestionFlowActivityTest.java | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java index 59120c98..828147dd 100644 --- a/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java +++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/paymentsreporting/service/AsyncSendMailService.java @@ -32,7 +32,7 @@ public class AsyncSendMailService { private String queueCapacity; - @Async("SendMailTaskExecutor") + @Async("sendMailTaskExecutor") @Retryable(value = MailException.class, maxAttemptsExpression = "${async.sendMail.retry.maxAttempts}", backoff = @Backoff(random = true, delayExpression = "${async.sendMail.retry.delay}", maxDelayExpression = "${async.sendMail.retry.maxDelay}", multiplierExpression = "${async.sendMail.retry.multiplier}")) @@ -62,7 +62,7 @@ private void recover(MailException e, String[] to, String[] cc, String subject, //TODO write fail to db or queue for retry, in case } - @Bean("SendMailTaskExecutor") + @Bean("sendMailTaskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(Integer.parseInt(corePoolSize)); diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java index 81817aba..1116871e 100644 --- a/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java +++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/SendEmailIngestionFlowActivityTest.java @@ -72,11 +72,6 @@ void setMailParams(String manageFlussoId, String templatename, Long fileSize){ ingestionFlowDTO.setIngestionFlowId(ingestionFlowId); ingestionFlowDTO.setDownloadedFileSize(fileSize); - /* - when(ingestionFlowDao.getIngestionFlow(ingestionFlowId)) - .thenReturn(Optional.of(ingestionFlowDTO)); - */ - DateFormat parser = new SimpleDateFormat("EEE, MMM dd yyyy, hh:mm:ss"); String actualDate = parser.format(new Date()); String mailText = "Il caricamento del file " + ingestionFlowDTO.getFileName();