Skip to content

Commit

Permalink
[SELC-6304] feat: added checks on product phases and roles (#504)
Browse files Browse the repository at this point in the history
  • Loading branch information
gaetano-miglionico authored Feb 6, 2025
1 parent 38a1a15 commit 5f13e6f
Show file tree
Hide file tree
Showing 2 changed files with 232 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
import it.pagopa.selfcare.dashboard.connector.model.product.mapper.ProductMapper;
import it.pagopa.selfcare.dashboard.connector.model.user.*;
import it.pagopa.selfcare.dashboard.core.exception.InvalidOnboardingStatusException;
import it.pagopa.selfcare.dashboard.core.exception.InvalidProductRoleException;
import it.pagopa.selfcare.onboarding.common.PartyRole;
import it.pagopa.selfcare.product.entity.PHASE_ADDITION_ALLOWED;
import it.pagopa.selfcare.product.entity.Product;
import it.pagopa.selfcare.product.entity.ProductRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
Expand Down Expand Up @@ -136,7 +140,8 @@ public String createUsers(String institutionId, String productId, UserToCreate u
log.trace("createOrUpdateUserByFiscalCode start");
log.debug("createOrUpdateUserByFiscalCode userDto = {}", userDto);
Institution institution = verifyOnboardingStatus(institutionId, productId);
List<CreateUserDto.Role> role = retrieveRole(productId, userDto.getProductRoles(), userDto.getRole());
Product product = verifyProductPhasesAndRoles(productId, institution.getInstitutionType(), userDto.getRole(), userDto.getProductRoles());
List<CreateUserDto.Role> role = retrieveRole(product, userDto.getProductRoles(), userDto.getRole());
String userId = userApiConnector.createOrUpdateUserByFiscalCode(institution, productId, userDto, role);
log.trace("createOrUpdateUserByFiscalCode end");
return userId;
Expand All @@ -148,7 +153,8 @@ public void addUserProductRoles(String institutionId, String productId, String u
log.debug("createOrUpdateUserByUserId userId = {}", userId);
Institution institution = verifyOnboardingStatus(institutionId, productId);
PartyRole partyRole = Optional.ofNullable(role).map(PartyRole::valueOf).orElse(null);
List<CreateUserDto.Role> roleDto = retrieveRole(productId, productRoles, partyRole);
Product product = verifyProductPhasesAndRoles(productId, institution.getInstitutionType(), partyRole, productRoles);
List<CreateUserDto.Role> roleDto = retrieveRole(product, productRoles, partyRole);
userApiConnector.createOrUpdateUserByUserId(institution, productId, userId, roleDto);
log.trace("createOrUpdateUserByUserId end");
}
Expand All @@ -163,14 +169,46 @@ private Institution verifyOnboardingStatus(String institutionId, String productI
else return institution;
}

/**
* <p>Get the product and verify if his phasesAdditionAllowed field allow to add users directly from dashboard with the specified partyRole and productRoles
* or throw an exception.</p>
*
* <p>Dashboard can add the user directly if the phasesAdditionAllowed contains the "dashboard" string else additional steps
* needs to be performed by the user (ex: sign additional documentation) and an onboarding procedure is required</p>
*
* <p>All the productRoles must be present in the roles of the ProductRoleInfo</p>
*
* @param productId product id
* @param institutionType institution type
* @param partyRole role to use
* @param productRoles a set of productRoles
* @return the product
* @throws InvalidProductRoleException if dashboard can not add the user directly with the partyRole specified
*/
private Product verifyProductPhasesAndRoles(String productId, String institutionType, PartyRole partyRole, Set<String> productRoles) {
final Product product = productsConnector.getProduct(productId);
return Optional.ofNullable(partyRole)
// If partyRole is present ==> get the ProductRoleInfo
.map(pr -> product.getRoleMappings(institutionType).get(pr))
// Check if phasesAdditionAllowed contains the "dashboard" string
.filter(pri -> pri.getPhasesAdditionAllowed().stream().anyMatch(PHASE_ADDITION_ALLOWED.DASHBOARD.value::equals))
// Obtain a set of validRoles from the product role info
.map(pri -> pri.getRoles().stream().map(ProductRole::getCode).collect(Collectors.toSet()))
// Check if all the productRoles in input are validRoles
.filter(validRoles -> validRoles.containsAll(productRoles))
// If all the previous filters are successful ==> Return the product
.map(i -> product)
// If any of the previous filters fail ==> throw exception
.orElseThrow(() -> new InvalidProductRoleException("The product doesn't allow adding users directly with these role and productRoles"));
}

/**
* This method is used to retrieve a list of roles for a given product.
* It maps each product role to a CreateUserDto.Role object, which includes the label and party role.
* To retrieve the party role, it uses the roleMappings of the product filtering by a white list of party roles (Only SUB_DELEGATE and OPERATOR are allowed
* as Role to be assigned to a user in add Users ProductRoles operation).
*/
private List<CreateUserDto.Role> retrieveRole(String productId, Set<String> productRoles, PartyRole partyRole) {
Product product = productsConnector.getProduct(productId);
private List<CreateUserDto.Role> retrieveRole(Product product, Set<String> productRoles, PartyRole partyRole) {
return productRoles.stream().map(productRole -> {
CreateUserDto.Role role = new CreateUserDto.Role();
role.setProductRole(productRole);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import it.pagopa.selfcare.dashboard.connector.model.institution.RelationshipState;
import it.pagopa.selfcare.dashboard.connector.model.user.*;
import it.pagopa.selfcare.dashboard.core.exception.InvalidOnboardingStatusException;
import it.pagopa.selfcare.dashboard.core.exception.InvalidProductRoleException;
import it.pagopa.selfcare.onboarding.common.PartyRole;
import it.pagopa.selfcare.product.entity.PHASE_ADDITION_ALLOWED;
import it.pagopa.selfcare.product.entity.Product;
Expand Down Expand Up @@ -289,7 +290,7 @@ void addUserProductRoles_ok() {
final String productId = "productId";
final String userId = "userId";
Set<String> productRoles = new HashSet<>(List.of("operator"));
String role = "MANAGER";
String role = "OPERATOR";
Product product = getProduct();

Institution institution = new Institution();
Expand All @@ -301,10 +302,7 @@ void addUserProductRoles_ok() {
CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(PartyRole.MANAGER);

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);
roleDto.setPartyRole(OPERATOR);

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);
Expand Down Expand Up @@ -365,6 +363,97 @@ void addUserProductRoles_invalidOnboardingStatus() {
verifyNoInteractions(userApiConnectorMock);
}

@Test
void addUserProductRolesWithInvalidPartyRole() {
final String institutionId = "institutionId";
final String productId = "productId";
final String userId = "userId";
final Set<String> productRoles = Set.of("operator");
final Product product = getProduct();

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, null),
"The product doesn't allow adding users directly with these role and productRoles");

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, "MANAGER"),
"The product doesn't allow adding users directly with these role and productRoles");
}

@Test
void addUserProductRolesWithInvalidPhasesAdditionAllowed() {
final String institutionId = "institutionId";
final String productId = "productId";
final String userId = "userId";
final Set<String> productRoles = Set.of("manager");
final String role = "MANAGER";

final Product product = getProduct();
final ProductRoleInfo productRoleInfoManager = new ProductRoleInfo();
productRoleInfoManager.setPhasesAdditionAllowed(List.of(PHASE_ADDITION_ALLOWED.DASHBOARD_ASYNC.value, PHASE_ADDITION_ALLOWED.ONBOARDING.value));
final ProductRole pr = new ProductRole();
pr.setCode("manager");
pr.setLabel("manager");
productRoleInfoManager.setRoles(List.of(pr));
product.setRoleMappings(Map.of(MANAGER, productRoleInfoManager));

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, role),
"The product doesn't allow adding users directly with these role and productRoles");
}

@Test
void addUserProductRolesWithInvalidProductRoles() {
final String institutionId = "institutionId";
final String productId = "productId";
final String userId = "userId";
final Set<String> productRoles = Set.of("operator2", "operator0", "operator1");
final String role = "OPERATOR";

final Product product = getProduct();
final ProductRoleInfo productRoleInfoOperator = new ProductRoleInfo();
productRoleInfoOperator.setPhasesAdditionAllowed(List.of(PHASE_ADDITION_ALLOWED.DASHBOARD_ASYNC.value, PHASE_ADDITION_ALLOWED.DASHBOARD.value));
final ProductRole pr1 = new ProductRole();
pr1.setCode("operator1");
pr1.setLabel("operator1");
final ProductRole pr2 = new ProductRole();
pr2.setCode("operator2");
pr2.setLabel("operator2");
productRoleInfoOperator.setRoles(List.of(pr1, pr2));
product.setRoleMappings(Map.of(PartyRole.OPERATOR, productRoleInfoOperator));

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, role),
"The product doesn't allow adding users directly with these role and productRoles");
}

@Test
void createUsersByFiscalCode() {

Expand All @@ -374,7 +463,7 @@ void createUsersByFiscalCode() {
UserToCreate userToCreate = new UserToCreate();
HashSet<String> productRoles = new HashSet<>();
productRoles.add(productRole);
userToCreate.setRole(PartyRole.MANAGER);
userToCreate.setRole(OPERATOR);
userToCreate.setProductRoles(productRoles);

Product product = getProduct();
Expand All @@ -389,7 +478,7 @@ void createUsersByFiscalCode() {
CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(MANAGER);
roleDto.setPartyRole(OPERATOR);


when(productsConnectorMock.getProduct(productId)).thenReturn(product);
Expand Down Expand Up @@ -418,7 +507,7 @@ void createUsersByFiscalCodeWithPartyROle() {
UserToCreate userToCreate = new UserToCreate();
HashSet<String> productRoles = new HashSet<>();
productRoles.add(productRole);
userToCreate.setRole(PartyRole.MANAGER);
userToCreate.setRole(OPERATOR);
userToCreate.setProductRoles(productRoles);

Product product = getProduct();
Expand All @@ -432,7 +521,7 @@ void createUsersByFiscalCodeWithPartyROle() {
CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(PartyRole.MANAGER);
roleDto.setPartyRole(OPERATOR);

when(productsConnectorMock.getProduct(productId)).thenReturn(product);

Expand Down Expand Up @@ -470,6 +559,98 @@ void createUsersByFiscalCodeWithOnboardingNotActive() {
verifyNoMoreInteractions(userApiConnectorMock);
}

@Test
void createUsersByFiscalCodeWithInvalidPartyRole() {
final String institutionId = "institutionId";
final String productId = "productId";
final UserToCreate userToCreate = new UserToCreate();
final Set<String> productRoles = Set.of("manager");
userToCreate.setRole(MANAGER);
userToCreate.setProductRoles(productRoles);

final Product product = getProduct();

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(productsConnectorMock.getProduct(productId)).thenReturn(product);
when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.createUsers(institutionId, productId, userToCreate),
"The product doesn't allow adding users directly with these role and productRoles");
}

@Test
void createUsersByFiscalCodeWithInvalidPhasesAdditionAllowed() {
final String institutionId = "institutionId";
final String productId = "productId";
final UserToCreate userToCreate = new UserToCreate();
final Set<String> productRoles = Set.of("manager");
userToCreate.setRole(MANAGER);
userToCreate.setProductRoles(productRoles);

final Product product = getProduct();
final ProductRoleInfo productRoleInfoManager = new ProductRoleInfo();
productRoleInfoManager.setPhasesAdditionAllowed(List.of(PHASE_ADDITION_ALLOWED.DASHBOARD_ASYNC.value, PHASE_ADDITION_ALLOWED.ONBOARDING.value));
final ProductRole pr = new ProductRole();
pr.setCode("manager");
pr.setLabel("manager");
productRoleInfoManager.setRoles(List.of(pr));
product.setRoleMappings(Map.of(MANAGER, productRoleInfoManager));

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(productsConnectorMock.getProduct(productId)).thenReturn(product);
when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.createUsers(institutionId, productId, userToCreate),
"The product doesn't allow adding users directly with these role and productRoles");
}

@Test
void createUsersByFiscalCodeWithInvalidProductRoles() {
final String institutionId = "institutionId";
final String productId = "productId";
final UserToCreate userToCreate = new UserToCreate();
final Set<String> productRoles = Set.of("operator2", "operator0", "operator1");
userToCreate.setRole(OPERATOR);
userToCreate.setProductRoles(productRoles);

final Product product = getProduct();
final ProductRoleInfo productRoleInfoOperator = new ProductRoleInfo();
productRoleInfoOperator.setPhasesAdditionAllowed(List.of(PHASE_ADDITION_ALLOWED.DASHBOARD_ASYNC.value, PHASE_ADDITION_ALLOWED.DASHBOARD.value));
final ProductRole pr1 = new ProductRole();
pr1.setCode("operator1");
pr1.setLabel("operator1");
final ProductRole pr2 = new ProductRole();
pr2.setCode("operator2");
pr2.setLabel("operator2");
productRoleInfoOperator.setRoles(List.of(pr1, pr2));
product.setRoleMappings(Map.of(PartyRole.OPERATOR, productRoleInfoOperator));

final Institution institution = new Institution();
final OnboardedProduct onboardedProduct = new OnboardedProduct();
onboardedProduct.setProductId(productId);
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

when(productsConnectorMock.getProduct(productId)).thenReturn(product);
when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);

assertThrows(InvalidProductRoleException.class,
() -> userV2ServiceImpl.createUsers(institutionId, productId, userToCreate),
"The product doesn't allow adding users directly with these role and productRoles");
}

private static Product getProduct() {
Product product = new Product();
Map<PartyRole, it.pagopa.selfcare.product.entity.ProductRoleInfo> map = new EnumMap<>(PartyRole.class);
Expand Down

0 comments on commit 5f13e6f

Please sign in to comment.