Skip to content

Commit

Permalink
feat: [P4PU-000] Promote to UAT (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
Giuseppe-LaManna authored Oct 16, 2024
2 parents b1af35c + 5aa487f commit 9038568
Show file tree
Hide file tree
Showing 22 changed files with 480 additions and 180 deletions.
40 changes: 40 additions & 0 deletions openapi/pagopa-arc-be.openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,46 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorDTO'
/notices/{eventId}/receipt:
get:
tags:
- arc notices
summary: "Retrieve notice receipt from arc"
operationId: getNoticeReceipt
security:
- bearerAuth: [ ]
parameters:
- name: eventId
in: path
description: "A unique id that identifies a notice"
required: true
schema:
type: string
responses:
'200':
description: "Obtained PDF notice receipt"
content:
application/pdf:
schema:
type: string
format: binary
'401':
description: "Wrong or missing function key"
'404':
description: "Notice receipt not found"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorDTO'
example:
error: "receipt_not_found_error"
error_description: "string"
'500':
description: "Internal Server Error"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorDTO'
/payment-notices:
get:
tags:
Expand Down
365 changes: 203 additions & 162 deletions postman/pagopa-arc-E2E.postman_collection.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/main/java/it/gov/pagopa/arc/config/OAuth2LoginConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package it.gov.pagopa.arc.config;

import it.gov.pagopa.arc.security.CustomAuthenticationFailureHandler;
import it.gov.pagopa.arc.security.CustomEntryPoint;
import it.gov.pagopa.arc.security.CustomAuthenticationEntryPoint;
import it.gov.pagopa.arc.security.CustomLogoutHandler;
import it.gov.pagopa.arc.security.CustomLogoutSuccessHandler;
import it.gov.pagopa.arc.security.InMemoryOAuth2AuthorizationRequestRepository;
Expand Down Expand Up @@ -60,7 +60,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.logoutSuccessHandler(customLogoutSuccessHandler)
)
.exceptionHandling(exceptionHandling -> exceptionHandling
.authenticationEntryPoint(new CustomEntryPoint())
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
)

.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import it.gov.pagopa.arc.connector.bizevents.dto.paidnotice.BizEventsPaidNoticeDetailsDTO;
import it.gov.pagopa.arc.dto.NoticeRequestDTO;
import it.gov.pagopa.arc.dto.NoticesListResponseDTO;
import org.springframework.core.io.Resource;

public interface BizEventsPaidNoticeConnector {
NoticesListResponseDTO getPaidNoticeList(String fiscalCode, NoticeRequestDTO noticeRequestDTO);
BizEventsPaidNoticeDetailsDTO getPaidNoticeDetails(String userId, String userFiscalCode, String eventId);
Resource getPaidNoticeReceipt(String userId, String userFiscalCode, String eventId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import it.gov.pagopa.arc.dto.mapper.bizevents.paidnotice.BizEventsPaidNoticeDTO2NoticesListResponseDTOMapper;
import it.gov.pagopa.arc.exception.custom.BizEventsInvocationException;
import it.gov.pagopa.arc.exception.custom.BizEventsPaidNoticeNotFoundException;
import it.gov.pagopa.arc.exception.custom.BizEventsReceiptNotFoundException;
import it.gov.pagopa.arc.model.generated.NoticesListDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -81,6 +83,18 @@ public BizEventsPaidNoticeDetailsDTO getPaidNoticeDetails(String userId, String
}
}

@Override
public Resource getPaidNoticeReceipt(String userId, String userFiscalCode, String eventId) {
try {
return bizEventsPaidNoticeRestClient.paidNoticeReceipt(apikey, userFiscalCode, eventId);
}catch (FeignException e){
if (e.status() == HttpStatus.NOT_FOUND.value()){
throw new BizEventsReceiptNotFoundException("An error occurred handling request from biz-Events to retrieve notice receipt with event id [%s] for the current user with userId [%s]".formatted(eventId, userId));
}
throw new BizEventsInvocationException(ERROR_MESSAGE_INVOCATION_EXCEPTION);
}
}

private NoticesListResponseDTO handleNotFound(){
NoticesListDTO noticesListDTO = NoticesListDTO.builder()
.notices(new ArrayList<>())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import feign.Response;
import it.gov.pagopa.arc.connector.bizevents.dto.paidnotice.BizEventsPaidNoticeDetailsDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.HttpStatus;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(
name = "biz-events-paid-notice",
Expand All @@ -15,8 +18,6 @@ public interface BizEventsPaidNoticeRestClient {
@GetMapping(
value = "/paids",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
Response paidNoticeList(
@RequestHeader(value = "Ocp-Apim-Subscription-Key") String apikey,
@RequestHeader(value = "x-fiscal-code") String fiscalCode,
Expand All @@ -31,11 +32,17 @@ Response paidNoticeList(
@GetMapping(
value = "/paids/{event-id}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
BizEventsPaidNoticeDetailsDTO paidNoticeDetails(
@RequestHeader(value = "Ocp-Apim-Subscription-Key") String apikey,
@RequestHeader(value = "x-fiscal-code") String fiscalCode,
@PathVariable(value = "event-id") String eventId
);

@GetMapping(
value = "/paids/{event-id}/pdf")
Resource paidNoticeReceipt(
@RequestHeader(value = "Ocp-Apim-Subscription-Key") String apikey,
@RequestHeader(value = "x-fiscal-code") String fiscalCode,
@PathVariable(value = "event-id") String eventId
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import it.gov.pagopa.arc.service.NoticesService;
import it.gov.pagopa.arc.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

Expand Down Expand Up @@ -51,4 +52,14 @@ public ResponseEntity<NoticeDetailsDTO> getNoticeDetails(String eventId) {

return ResponseEntity.ok().body(noticeDetailsDTO);
}

@Override
public ResponseEntity<Resource> getNoticeReceipt(String eventId) {
String userFiscalCode = SecurityUtils.getUserFiscalCode();
String userId = SecurityUtils.getUserId();

Resource receipt = noticesService.retrieveNoticeReceipt(userId, userFiscalCode, eventId);

return ResponseEntity.ok().body(receipt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public ResponseEntity<ErrorDTO> handleBizEventsNoticeNotFoundException(RuntimeEx
return handleArcErrorException(ex, request, HttpStatus.NOT_FOUND, ErrorDTO.ErrorEnum.NOTICE_NOT_FOUND_ERROR);
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorDTO> handleGenericRuntimeException(RuntimeException ex, HttpServletRequest request){
return handleArcErrorException(ex, request, HttpStatus.INTERNAL_SERVER_ERROR, ErrorDTO.ErrorEnum.GENERIC_ERROR);
}

private static ResponseEntity<ErrorDTO> handleArcErrorException(RuntimeException ex, HttpServletRequest request, HttpStatus httpStatus, ErrorDTO.ErrorEnum errorEnum) {
String message = ex.getMessage();
log.info("A {} occurred handling request {}: HttpStatus {} - {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

public class CustomEntryPoint implements AuthenticationEntryPoint {
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/it/gov/pagopa/arc/service/NoticesService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import it.gov.pagopa.arc.dto.NoticeRequestDTO;
import it.gov.pagopa.arc.dto.NoticesListResponseDTO;
import it.gov.pagopa.arc.model.generated.NoticeDetailsDTO;
import org.springframework.core.io.Resource;

public interface NoticesService {
NoticesListResponseDTO retrieveNoticesAndToken(String userFiscalCode, String userId, NoticeRequestDTO noticeRequestDTO);
NoticeDetailsDTO retrieveNoticeDetails(String userId, String userFiscalCode, String eventId);
Resource retrieveNoticeReceipt(String userId, String userFiscalCode, String eventId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import it.gov.pagopa.arc.model.generated.NoticeDetailsDTO;
import it.gov.pagopa.arc.service.bizevents.BizEventsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

@Slf4j
Expand All @@ -31,4 +32,11 @@ public NoticeDetailsDTO retrieveNoticeDetails(String userId, String userFiscalCo

return bizEventsService.retrievePaidNoticeDetailsFromBizEvents(userId, userFiscalCode, eventId);
}

@Override
public Resource retrieveNoticeReceipt(String userId, String userFiscalCode, String eventId) {
log.info("[GET_NOTICE_RECEIPT] The current user with user id : {}, has requested to retrieve paid notice receipt for paid notice with id {}", userId, eventId);

return bizEventsService.retrievePaidNoticeReceiptFromBizEvents(userId, userFiscalCode, eventId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public interface BizEventsService {
Resource retrieveTransactionReceiptFromBizEvents(String transactionId);
NoticesListResponseDTO retrievePaidListFromBizEvents(String userFiscalCode, NoticeRequestDTO noticeRequestDTO);
NoticeDetailsDTO retrievePaidNoticeDetailsFromBizEvents(String userId, String userFiscalCode, String eventId);
Resource retrievePaidNoticeReceiptFromBizEvents(String userId, String userFiscalCode, String eventId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ public NoticeDetailsDTO retrievePaidNoticeDetailsFromBizEvents(String userId, St
BizEventsPaidNoticeDetailsDTO paidNoticeDetails = bizEventsPaidNoticeConnector.getPaidNoticeDetails(userId, userFiscalCode, eventId);
return bizEventsPaidNoticeDetailsDTO2NoticeDetailsDTOMapper.toNoticeDetailsDTO(paidNoticeDetails);
}

@Override
public Resource retrievePaidNoticeReceiptFromBizEvents(String userId, String userFiscalCode, String eventId) {
return bizEventsPaidNoticeConnector.getPaidNoticeReceipt(userId, userFiscalCode, eventId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import it.gov.pagopa.arc.dto.mapper.bizevents.paidnotice.BizEventsPaidNoticeDTO2NoticesListResponseDTOMapper;
import it.gov.pagopa.arc.exception.custom.BizEventsInvocationException;
import it.gov.pagopa.arc.exception.custom.BizEventsPaidNoticeNotFoundException;
import it.gov.pagopa.arc.exception.custom.BizEventsReceiptNotFoundException;
import it.gov.pagopa.arc.fakers.NoticeRequestDTOFaker;
import it.gov.pagopa.arc.model.generated.NoticeDTO;
import it.gov.pagopa.arc.model.generated.NoticesListDTO;
Expand All @@ -32,11 +33,14 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.core.io.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -293,4 +297,36 @@ void givenEventIdWhenErrorThenThrowBizEventsInvocationException() {
() -> bizEventsPaidNoticeConnector.getPaidNoticeDetails("USER_ID","DUMMY_FISCAL_CODE_PAID_NOTICE_DETAILS_ERROR", "EVENT_ID_ERROR_1"));
Assertions.assertEquals("An error occurred handling request from biz-Events", bizEventsInvocationException.getMessage());
}

@Test
void givenEventIdWhenCallBizEventsPaidNoticeConnectorThenReturnNoticeReceipt() throws IOException {
//given
//when
Resource noticeReceipt = bizEventsPaidNoticeConnector.getPaidNoticeReceipt("USER_ID","DUMMY_FISCAL_CODE_PAID_NOTICE_RECEIPT_OK", "EVENT_ID_OK_1");

//then
Assertions.assertNotNull(noticeReceipt);
Assertions.assertTrue(noticeReceipt.exists());
byte[] expectedContent = Files.readAllBytes(Paths.get("src/test/resources/stub/__files/testReceiptPdfFile.pdf"));
byte[] actualContent = noticeReceipt.getInputStream().readAllBytes();
assertArrayEquals(expectedContent, actualContent);
}

@Test
void givenEventIdWhenReceiptNotFoundThenReturnException() {
//given
//when
BizEventsReceiptNotFoundException bizEventsReceiptNotFoundException = assertThrows(BizEventsReceiptNotFoundException.class,
() -> bizEventsPaidNoticeConnector.getPaidNoticeReceipt("USER_ID","DUMMY_FISCAL_CODE_PAID_NOTICE_RECEIPT_NOT_FOUND", "EVENT_ID_NOT_FOUND_1"));
Assertions.assertEquals("An error occurred handling request from biz-Events to retrieve notice receipt with event id [EVENT_ID_NOT_FOUND_1] for the current user with userId [USER_ID]", bizEventsReceiptNotFoundException.getMessage());
}

@Test
void givenEventIdWhenReceiptErrorThenThrowBizEventsInvocationException() {
//When
//Then
BizEventsInvocationException bizEventsInvocationException = assertThrows(BizEventsInvocationException.class,
() -> bizEventsPaidNoticeConnector.getPaidNoticeReceipt("USER_ID","DUMMY_FISCAL_CODE_PAID_NOTICE_RECEIPT_ERROR", "EVENT_ID_ERROR_2"));
Assertions.assertEquals("An error occurred handling request from biz-Events", bizEventsInvocationException.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import it.gov.pagopa.arc.dto.NoticesListResponseDTO;
import it.gov.pagopa.arc.dto.mapper.NoticeRequestDTOMapper;
import it.gov.pagopa.arc.fakers.NoticeDTOFaker;
import it.gov.pagopa.arc.fakers.NoticeDetailsDTOFaker;
import it.gov.pagopa.arc.fakers.NoticeRequestDTOFaker;
import it.gov.pagopa.arc.fakers.auth.IamUserInfoDTOFaker;
import it.gov.pagopa.arc.fakers.NoticeDetailsDTOFaker;
import it.gov.pagopa.arc.model.generated.NoticeDTO;
import it.gov.pagopa.arc.model.generated.NoticeDetailsDTO;
import it.gov.pagopa.arc.model.generated.NoticesListDTO;
Expand All @@ -26,13 +26,17 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import static org.hamcrest.CoreMatchers.nullValue;
Expand Down Expand Up @@ -171,4 +175,25 @@ void givenEventIdWhenCallGetNoticeDetailsThenReturnNoticeDetails() throws Except
Assertions.assertEquals(noticeDetailsDTO, resultResponse);
}

@Test
void givenEventIdWhenCallGetNoticeReceiptThenReturnNoticeReceipt() throws Exception {
//Given
Resource receipt = new FileSystemResource("src/test/resources/stub/__files/testReceiptPdfFile.pdf");

Mockito.when( noticesServiceMock.retrieveNoticeReceipt(USER_ID, DUMMY_FISCAL_CODE, EVENT_ID)).thenReturn(receipt);

//When
MvcResult result = mockMvc.perform(
get("/notices/{eventId}/receipt", EVENT_ID)
).andExpect(status().is2xxSuccessful())
.andReturn();

//Then
byte[] expectedContent = Files.readAllBytes(Paths.get("src/test/resources/stub/__files/testReceiptPdfFile.pdf"));
byte[] actualContent = result.getResponse().getContentAsByteArray();

Assertions.assertNotNull(actualContent);
Assertions.assertArrayEquals(expectedContent, actualContent);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,15 @@ void givenRequestWhenBizEventsServiceReturnNotFoundErrorThenHandleBizEventsPaidN
Assertions.assertTrue(memoryAppender.getLoggedEvents().get(0).getFormattedMessage().contains("A class it.gov.pagopa.arc.exception.custom.BizEventsPaidNoticeNotFoundException occurred handling request GET /test/EVENT_ID: HttpStatus 404 - Error"));
}

@Test
void givenGenericErrorThenThrowException() throws Exception {
doThrow(new RuntimeException("Error")).when(testControllerSpy).testEndpoint();

mockMvc.perform(MockMvcRequestBuilders.get("/test")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().is(500))
.andExpect(MockMvcResultMatchers.jsonPath("$.error").value("generic_error"));
}

}
Loading

0 comments on commit 9038568

Please sign in to comment.