Skip to content

Commit

Permalink
[PNPG-224] feat: added check on infocamere to prevent user which is n…
Browse files Browse the repository at this point in the history
…ot LR to onboard the PG (#349)
  • Loading branch information
empassaro authored Sep 26, 2024
1 parent ad47e37 commit 36d16e2
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface InstitutionService {

void onboardingProductV2(OnboardingData onboardingData);

void onboardingCompanyV2(OnboardingData onboardingData);
void onboardingCompanyV2(OnboardingData onboardingData, String userFiscalCode);

void onboardingProduct(OnboardingData onboardingData);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class InstitutionServiceImpl implements InstitutionService {
public static final String ONE_OTHER_PARAMETER_PROVIDED = "At least one other parameter must be provided along with productId";

private static final String REQUIRED_AGGREGATE_INSTITUTIONS = "Aggregate institutions are required if given institution is an Aggregator";

private static final String ONBOARDING_COMPANY_NOT_ALLOWED = "The selected business does not belong to the user";
static final String DESCRIPTION_TO_REPLACE_REGEX = " - COMUNE";
private final OnboardingMsConnector onboardingMsConnector;
private final PartyConnector partyConnector;
Expand Down Expand Up @@ -118,13 +120,56 @@ public void onboardingPaAggregator(OnboardingData onboardingData) {
}

@Override
public void onboardingCompanyV2(OnboardingData onboardingData) {
public void onboardingCompanyV2(OnboardingData onboardingData, String userFiscalCode) {
log.trace("onboardingProductAsync start");
log.debug("onboardingProductAsync onboardingData = {}", onboardingData);
verifyIfUserIsManagerOfBusiness(onboardingData.getTaxCode(), userFiscalCode, onboardingData.getOrigin());
onboardingMsConnector.onboardingCompany(onboardingData);
log.trace("onboarding end");
}

private void verifyIfUserIsManagerOfBusiness(String businessTaxCode, String userFiscalCode, String origin) {
switch (Origin.fromValue(origin)) {
case INFOCAMERE:
verifyIfUserIsManagerOfBusinessOnInfocamere(businessTaxCode, userFiscalCode);
break;
case ADE:
verifyIfUserIsManagerOfBusinessOnAde(businessTaxCode, userFiscalCode);
break;
default:
log.error("Origin {} is not supported", origin);
throw new InvalidRequestException("Origin not supported");
}
}

private void verifyIfUserIsManagerOfBusinessOnInfocamere(String businessTaxCode, String userFiscalCode) {
log.debug(LogUtils.CONFIDENTIAL_MARKER, "Checking if user with fiscal code {} is manager of business with tax code {} on Infocamere",
userFiscalCode, businessTaxCode);
InstitutionInfoIC userBusinesses = partyRegistryProxyConnector.getInstitutionsByUserFiscalCode(userFiscalCode);
if (!isICBusinessRelatedToUser(userBusinesses, businessTaxCode)) {
log.error("User is not authorized to onboard business with tax code {}", businessTaxCode);
throw new OnboardingNotAllowedException(ONBOARDING_COMPANY_NOT_ALLOWED);
}
}

private boolean isICBusinessRelatedToUser(InstitutionInfoIC institutionInfoIC, String businessTaxCode) {
return institutionInfoIC != null
&& !CollectionUtils.isEmpty(institutionInfoIC.getBusinesses())
&& institutionInfoIC.getBusinesses()
.stream()
.anyMatch(business -> Objects.equals(business.getBusinessTaxId(), businessTaxCode));
}

private void verifyIfUserIsManagerOfBusinessOnAde(String businessTaxCode, String userFiscalCode) {
log.debug(LogUtils.CONFIDENTIAL_MARKER, "Checking if user with fiscal code {} is manager of business with tax code {} on ADE",
userFiscalCode, businessTaxCode);
MatchInfoResult matchInfoResult = partyRegistryProxyConnector.matchInstitutionAndUser(businessTaxCode, userFiscalCode);
if (Objects.isNull(matchInfoResult) || !matchInfoResult.isVerificationResult()) {
log.error("User is not authorized to onboard business with tax code {}", businessTaxCode);
throw new OnboardingNotAllowedException(ONBOARDING_COMPANY_NOT_ALLOWED);
}
}

@Override
public void onboardingProduct(OnboardingData onboardingData) {
log.trace("onboarding start");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,118 @@ void onboardingProductAsync() {


@Test
void onboardingCompanyV2() {
void onboardingCompanyV2SuccessfullyWhenBusinessIsFoundOnInfocamere() {
// given
OnboardingData onboardingData = mockInstance(new OnboardingData(), "setInstitutionType", "setUsers");
onboardingData.setOrigin(Origin.INFOCAMERE.getValue());
onboardingData.setInstitutionType(InstitutionType.PG);
onboardingData.setUsers(List.of(dummyManager, dummyDelegate));
String managerTaxCode = dummyManager.getTaxCode();

InstitutionInfoIC institutionInfoIC = new InstitutionInfoIC();
institutionInfoIC.setLegalTaxId(managerTaxCode);
BusinessInfoIC businessInfoIC = new BusinessInfoIC();
businessInfoIC.setBusinessName("businessName");
businessInfoIC.setBusinessTaxId(onboardingData.getTaxCode());
institutionInfoIC.setBusinesses(List.of(businessInfoIC));

when(partyRegistryProxyConnectorMock.getInstitutionsByUserFiscalCode(anyString()))
.thenReturn(institutionInfoIC);
// when
institutionService.onboardingCompanyV2(onboardingData, managerTaxCode);
// then
verify(partyRegistryProxyConnectorMock, times(1))
.getInstitutionsByUserFiscalCode(managerTaxCode);
verify(partyRegistryProxyConnectorMock, times(0))
.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode);
verify(onboardingMsConnector, times(1))
.onboardingCompany(any());
}

@Test
void onboardingCompanyV2SuccesfullyWhenBusinessIsFoundOnAde() {
// given
OnboardingData onboardingData = mockInstance(new OnboardingData(), "setInstitutionType", "setUsers");
onboardingData.setOrigin(Origin.ADE.getValue());
onboardingData.setInstitutionType(InstitutionType.PG);
onboardingData.setUsers(List.of(dummyManager, dummyDelegate));
String managerTaxCode = dummyManager.getTaxCode();

MatchInfoResult matchInfoResult = new MatchInfoResult();
matchInfoResult.setVerificationResult(true);
when(partyRegistryProxyConnectorMock.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode))
.thenReturn(matchInfoResult);
// when
institutionService.onboardingCompanyV2(onboardingData);
institutionService.onboardingCompanyV2(onboardingData, managerTaxCode);
// then
verify(partyRegistryProxyConnectorMock, times(0))
.getInstitutionsByUserFiscalCode(managerTaxCode);
verify(partyRegistryProxyConnectorMock, times(1))
.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode);
verify(onboardingMsConnector, times(1))
.onboardingCompany(any());
}

@Test
void onboardingCompanyV2NotAllowedWhenBusinessIsNotRetrievedFromInfocamere() {
// given
OnboardingData onboardingData = mockInstance(new OnboardingData(), "setInstitutionType", "setUsers");
onboardingData.setOrigin(Origin.INFOCAMERE.getValue());
onboardingData.setInstitutionType(InstitutionType.PG);
onboardingData.setUsers(List.of(dummyManager, dummyDelegate));
String managerTaxCode = dummyManager.getTaxCode();

when(partyRegistryProxyConnectorMock.getInstitutionsByUserFiscalCode(managerTaxCode))
.thenReturn(new InstitutionInfoIC());
// when
Assertions.assertThrows(OnboardingNotAllowedException.class, () -> institutionService.onboardingCompanyV2(onboardingData, managerTaxCode));
// then
verify(partyRegistryProxyConnectorMock, times(1))
.getInstitutionsByUserFiscalCode(managerTaxCode);
verify(partyRegistryProxyConnectorMock, times(0))
.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode);
verify(onboardingMsConnector, times(0))
.onboardingCompany(any());
}

@Test
void onboardingCompanyV2NotAllowedWhenBusinessIsNotRetrievedFromAde() {
// given
OnboardingData onboardingData = mockInstance(new OnboardingData(), "setInstitutionType", "setUsers");
onboardingData.setOrigin(Origin.ADE.getValue());
onboardingData.setInstitutionType(InstitutionType.PG);
onboardingData.setUsers(List.of(dummyManager, dummyDelegate));
String managerTaxCode = dummyManager.getTaxCode();

when(partyRegistryProxyConnectorMock.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode))
.thenReturn(new MatchInfoResult());
// when
Assertions.assertThrows(OnboardingNotAllowedException.class, () -> institutionService.onboardingCompanyV2(onboardingData, managerTaxCode));
// then
verify(partyRegistryProxyConnectorMock, times(0))
.getInstitutionsByUserFiscalCode(managerTaxCode);
verify(partyRegistryProxyConnectorMock, times(1))
.matchInstitutionAndUser(onboardingData.getTaxCode(), managerTaxCode);
verify(onboardingMsConnector, times(0))
.onboardingCompany(any());
}

@Test
void onboardingCompanyV2NotAllowedWhenOriginIsNotAllowed() {
OnboardingData onboardingData = mockInstance(new OnboardingData(), "setInstitutionType", "setUsers");
onboardingData.setOrigin("IPA");

// when
Assertions.assertThrows(InvalidRequestException.class, () -> institutionService.onboardingCompanyV2(onboardingData, dummyManager.getTaxCode()));
// then
verify(partyRegistryProxyConnectorMock, times(0))
.getInstitutionsByUserFiscalCode(dummyManager.getTaxCode());
verify(partyRegistryProxyConnectorMock, times(0))
.matchInstitutionAndUser(onboardingData.getTaxCode(), dummyManager.getTaxCode());
verify(onboardingMsConnector, times(0))
.onboardingCompany(any());
}

@Test
void onboardingPaAggregator() {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import it.pagopa.selfcare.commons.base.logging.LogUtils;
import it.pagopa.selfcare.commons.base.security.SelfCareUser;
import it.pagopa.selfcare.commons.web.model.Problem;
import it.pagopa.selfcare.commons.web.security.JwtAuthenticationToken;
import it.pagopa.selfcare.onboarding.core.InstitutionService;
import it.pagopa.selfcare.onboarding.web.model.*;
import it.pagopa.selfcare.onboarding.web.model.mapper.InstitutionMapper;
import it.pagopa.selfcare.onboarding.web.model.mapper.OnboardingResourceMapper;
import lombok.extern.slf4j.Slf4j;
import org.owasp.encoder.Encode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.security.Principal;
import java.util.List;

import static org.springframework.http.MediaType.APPLICATION_PROBLEM_JSON_VALUE;
Expand Down Expand Up @@ -71,10 +75,12 @@ public void onboarding(@RequestBody @Valid OnboardingProductDto request) {
@PostMapping(value = "/company/onboarding")
@ResponseStatus(HttpStatus.CREATED)
@ApiOperation(value = "", notes = "${swagger.onboarding.institutions.api.onboarding.subunit}")
public void onboarding(@RequestBody @Valid CompanyOnboardingDto request) {
public void onboarding(@RequestBody @Valid CompanyOnboardingDto request, Principal principal) {
log.trace(ONBOARDING_START);
log.debug("onboarding request = {}", request);
institutionService.onboardingCompanyV2(onboardingResourceMapper.toEntity(request));
log.debug("onboarding request = {}", Encode.forJava(request.toString()));
JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) principal;
SelfCareUser selfCareUser = (SelfCareUser) jwtAuthenticationToken.getPrincipal();
institutionService.onboardingCompanyV2(onboardingResourceMapper.toEntity(request), selfCareUser.getFiscalCode());
log.trace(ONBOARDING_END);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.pagopa.selfcare.commons.base.security.SelfCareUser;
import it.pagopa.selfcare.commons.base.utils.ProductId;
import it.pagopa.selfcare.commons.web.security.JwtAuthenticationToken;
import it.pagopa.selfcare.onboarding.connector.model.institutions.Institution;
import it.pagopa.selfcare.onboarding.connector.model.onboarding.OnboardingData;
import it.pagopa.selfcare.onboarding.core.InstitutionService;
Expand All @@ -12,6 +14,7 @@
import it.pagopa.selfcare.onboarding.web.model.mapper.OnboardingResourceMapperImpl;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
Expand Down Expand Up @@ -97,10 +100,16 @@ void onboardingProductForAggregatorAsync(@Value("classpath:stubs/onboardingProdu

@Test
void onboardingCompany(@Value("classpath:stubs/onboardingCompanyDto.json") Resource onboardingDto) throws Exception {

//given
JwtAuthenticationToken mockPrincipal = Mockito.mock(JwtAuthenticationToken.class);
SelfCareUser selfCareUser = SelfCareUser.builder("example")
.fiscalCode("fiscalCode")
.build();
Mockito.when(mockPrincipal.getPrincipal()).thenReturn(selfCareUser);
// when
mvc.perform(MockMvcRequestBuilders
.post(BASE_URL + "/company/onboarding")
.principal(mockPrincipal)
.content(onboardingDto.getInputStream().readAllBytes())
.contentType(APPLICATION_JSON_VALUE)
.accept(APPLICATION_JSON_VALUE))
Expand All @@ -109,7 +118,7 @@ void onboardingCompany(@Value("classpath:stubs/onboardingCompanyDto.json") Resou
// then

verify(institutionServiceMock, times(1))
.onboardingCompanyV2(any(OnboardingData.class));
.onboardingCompanyV2(any(OnboardingData.class), anyString());
verifyNoMoreInteractions(institutionServiceMock);
}

Expand Down

0 comments on commit 36d16e2

Please sign in to comment.