Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SELC-5706] Feat: Added partyRole in request for CreateUser API and AddUserRole API #489

Merged
merged 3 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions app/src/main/resources/swagger/api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -3192,6 +3192,10 @@
"type" : "string"
}
},
"role" : {
"type" : "string",
"description" : "User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]"
},
"surname" : {
"type" : "string",
"description" : "User's surname"
Expand Down Expand Up @@ -3728,7 +3732,7 @@
},
"role" : {
"type" : "string",
"description" : "User's role",
"description" : "User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]",
"enum" : [ "ADMIN", "ADMIN_EA", "LIMITED" ]
},
"status" : {
Expand Down Expand Up @@ -3986,7 +3990,7 @@
},
"selcRole" : {
"type" : "string",
"description" : "User's role",
"description" : "User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]",
"enum" : [ "ADMIN", "ADMIN_EA", "LIMITED" ]
},
"status" : {
Expand Down Expand Up @@ -4070,7 +4074,7 @@
},
"role" : {
"type" : "string",
"description" : "User's role",
"description" : "User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]",
"enum" : [ "ADMIN", "ADMIN_EA", "LIMITED" ]
},
"status" : {
Expand Down Expand Up @@ -4495,6 +4499,10 @@
"items" : {
"type" : "string"
}
},
"role" : {
"type" : "string",
"description" : "User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package it.pagopa.selfcare.dashboard.connector.model.institution;

import it.pagopa.selfcare.onboarding.common.InstitutionType;
import lombok.Data;
import lombok.EqualsAndHashCode;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package it.pagopa.selfcare.dashboard.connector.model.user;

import it.pagopa.selfcare.onboarding.common.PartyRole;
import lombok.Data;

import java.util.Set;
Expand All @@ -10,5 +11,6 @@ public class UserToCreate {
private String surname;
private String taxCode;
private String email;
private PartyRole role;
private Set<String> productRoles;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ public interface UserV2Service {

String createUsers(String institutionId, String productId, UserToCreate userToCreate);

void addUserProductRoles(String institutionId, String productId, String userId, Set<String> productRoles);
void addUserProductRoles(String institutionId, String productId, String userId, Set<String> productRoles, String role);
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,20 @@ 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());
List<CreateUserDto.Role> role = retrieveRole(productId, userDto.getProductRoles(), userDto.getRole());
String userId = userApiConnector.createOrUpdateUserByFiscalCode(institution, productId, userDto, role);
log.trace("createOrUpdateUserByFiscalCode end");
return userId;
}

@Override
public void addUserProductRoles(String institutionId, String productId, String userId, Set<String> productRoles) {
public void addUserProductRoles(String institutionId, String productId, String userId, Set<String> productRoles, String role) {
log.trace("createOrUpdateUserByUserId start");
log.debug("createOrUpdateUserByUserId userId = {}", userId);
Institution institution = verifyOnboardingStatus(institutionId, productId);
List<CreateUserDto.Role> role = retrieveRole(productId, productRoles);
userApiConnector.createOrUpdateUserByUserId(institution, productId, userId, role);
PartyRole partyRole = Optional.ofNullable(role).map(PartyRole::valueOf).orElse(null);
List<CreateUserDto.Role> roleDto = retrieveRole(productId, productRoles, partyRole);
userApiConnector.createOrUpdateUserByUserId(institution, productId, userId, roleDto);
log.trace("createOrUpdateUserByUserId end");
}

Expand All @@ -172,21 +173,25 @@ private Institution verifyOnboardingStatus(String institutionId, String productI
* as Role to be assigned to a user in add Users ProductRoles operation).
* If the party role is not valid, it throws an InvalidProductRoleException.
*/
private List<CreateUserDto.Role> retrieveRole(String productId, Set<String> productRoles) {
private List<CreateUserDto.Role> retrieveRole(String productId, Set<String> productRoles, PartyRole partyRole) {
Product product = productsConnector.getProduct(productId);
return productRoles.stream().map(productRole -> {

CreateUserDto.Role role = new CreateUserDto.Role();
role.setProductRole(productRole);

//TODO https://pagopa.atlassian.net/browse/SELC-5706 for institutionType=null
role.setLabel(ProductMapper.getLabel(productRole, product.getRoleMappings(null)).orElse(null));

List<PartyRole> partyRoles = ProductUtils.validRolesByProductRole(product, PHASE_ADDITION_ALLOWED.DASHBOARD, productRole, null);
if(Objects.isNull(partyRoles) || partyRoles.isEmpty()){
throw new InvalidProductRoleException(String.format("Product role '%s' is not valid", productRole));
//TODO: https://pagopa.atlassian.net/browse/SELC-5757
if(Objects.isNull(partyRole)){
List<PartyRole> partyRoles = ProductUtils.validRolesByProductRole(product, PHASE_ADDITION_ALLOWED.DASHBOARD, productRole, null);
if(Objects.isNull(partyRoles) || partyRoles.isEmpty()){
throw new InvalidProductRoleException(String.format("Product role '%s' is not valid", productRole));
}
role.setPartyRole(partyRoles.get(0));
} else{
role.setPartyRole(partyRole);
}
role.setPartyRole(partyRoles.get(0));
return role;
}).toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ void addUserProductRoles_ok() {
final String productId = "productId";
final String userId = "userId";
Set<String> productRoles = new HashSet<>(List.of("operator"));
String role = "MANAGER";
Product product = getProduct();

Institution institution = new Institution();
Expand All @@ -299,24 +300,32 @@ void addUserProductRoles_ok() {
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

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);

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);
doNothing().when(userApiConnectorMock).createOrUpdateUserByUserId(eq(institution), eq(productId), eq(userId), anyList());
doNothing().when(userApiConnectorMock).createOrUpdateUserByUserId(institution, productId, userId, List.of(roleDto));

userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles);
userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, role);

verify(userApiConnectorMock, times(1))
.createOrUpdateUserByUserId(eq(institution), eq(productId), eq(userId), anyList());
.createOrUpdateUserByUserId(institution, productId, userId, List.of(roleDto));
verifyNoMoreInteractions(userApiConnectorMock);
}

@Test
void addUserProductRoles_invalidProductRole() {
void addUserProductRoles_ok_withoutPartyRole() {

final String institutionId = "institutionId";
final String productId = "productId";
final String userId = "userId";
Set<String> productRoles = new HashSet<>(List.of("role1"));
Set<String> productRoles = new HashSet<>(List.of("operator"));
Product product = getProduct();

Institution institution = new Institution();
Expand All @@ -325,25 +334,35 @@ void addUserProductRoles_invalidProductRole() {
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));

CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(PartyRole.OPERATOR);

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);
when(productsConnectorMock.getProduct(productId)).thenReturn(product);
doNothing().when(userApiConnectorMock).createOrUpdateUserByUserId(institution, productId, userId, List.of(roleDto));

Assertions.assertThrows(InvalidProductRoleException.class, () -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles));
userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, null);

verifyNoInteractions(userApiConnectorMock);
verify(userApiConnectorMock, times(1))
.createOrUpdateUserByUserId(institution, productId, userId, List.of(roleDto));
verifyNoMoreInteractions(userApiConnectorMock);
}


@Test
void addUserProductRoles_invalidOnboardingStatus() {

final String institutionId = "institutionId";
final String productId = "productId";
final String userId = "userId";
Set<String> productRoles = new HashSet<>(List.of("operator"));
String role = "MANAGER";

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(new Institution());

Assertions.assertThrows(InvalidOnboardingStatusException.class, () -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles));
Assertions.assertThrows(InvalidOnboardingStatusException.class, () -> userV2ServiceImpl.addUserProductRoles(institutionId, productId, userId, productRoles, role));

verifyNoInteractions(userApiConnectorMock);
}
Expand All @@ -367,9 +386,16 @@ void createUsersByFiscalCode() {
onboardedProduct.setStatus(RelationshipState.ACTIVE);
institution.setOnboarding(List.of(onboardedProduct));


CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(PartyRole.OPERATOR);


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

when(userApiConnectorMock.createOrUpdateUserByFiscalCode(eq(institution), eq(productId), eq(userToCreate), anyList())).thenReturn("userId");
when(userApiConnectorMock.createOrUpdateUserByFiscalCode(institution, productId, userToCreate, List.of(roleDto))).thenReturn("userId");

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);

Expand All @@ -380,10 +406,53 @@ void createUsersByFiscalCode() {
verify(userApiConnectorMock, times(1))
.createOrUpdateUserByFiscalCode(eq(institution), eq(productId), eq(userToCreate), captorRoles.capture());
assertEquals(captorRoles.getValue().get(0).getProductRole(), productRole);
assertEquals(captorRoles.getValue().get(0).getPartyRole(), roleDto.getPartyRole());
verifyNoMoreInteractions(userApiConnectorMock);
}

@Test
void createUsersByFiscalCodeWithPartyROle() {

final String institutionId = "institutionId";
final String productId = "productId";
final String productRole = "operator";
UserToCreate userToCreate = new UserToCreate();
HashSet<String> productRoles = new HashSet<>();
productRoles.add(productRole);
userToCreate.setRole(PartyRole.MANAGER);
userToCreate.setProductRoles(productRoles);

Product product = getProduct();

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

CreateUserDto.Role roleDto = new CreateUserDto.Role();
roleDto.setProductRole("operator");
roleDto.setLabel("operator");
roleDto.setPartyRole(PartyRole.MANAGER);

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

when(userApiConnectorMock.createOrUpdateUserByFiscalCode(institution, productId, userToCreate, List.of(roleDto))).thenReturn("userId");

when(msCoreConnectorMock.getInstitution(institutionId)).thenReturn(institution);

String userId = userV2ServiceImpl.createUsers(institutionId, productId, userToCreate);

assertNotNull(userId);
ArgumentCaptor<List<CreateUserDto.Role>> captorRoles = ArgumentCaptor.forClass(List.class);
verify(userApiConnectorMock, times(1))
.createOrUpdateUserByFiscalCode(eq(institution), eq(productId), eq(userToCreate), captorRoles.capture());
assertEquals(captorRoles.getValue().get(0).getProductRole(), productRole);
assertEquals(captorRoles.getValue().get(0).getPartyRole(), roleDto.getPartyRole());
verifyNoMoreInteractions(userApiConnectorMock);
}


@Test
void createUsersByFiscalCodeWithOnboardingNotActive() {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package it.pagopa.selfcare.dashboard.web.controller;

import com.azure.core.annotation.QueryParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
Expand Down Expand Up @@ -105,7 +106,6 @@ public UserIdResource createInstitutionProductUser(@ApiParam("${swagger.dashboar
@ApiParam("${swagger.dashboard.products.model.id}")
@PathVariable("productId")
String productId,
@ApiParam("${swagger.dashboard.user.model.role}")
@RequestBody
@Valid
CreateUserDto user) {
Expand Down Expand Up @@ -139,7 +139,7 @@ public void addUserProductRoles(@ApiParam("${swagger.dashboard.institutions.mode
UserProductRoles userProductRoles) {
log.trace("addUserProductRoles start");
log.debug("institutionId = {}, productId = {}, userId = {}, userProductRoles = {}", institutionId, productId, userId, userProductRoles);
userService.addUserProductRoles(institutionId, productId, userId, userProductRoles.getProductRoles());
userService.addUserProductRoles(institutionId, productId, userId, userProductRoles.getProductRoles(), userProductRoles.getRole());
log.trace("addUserProductRoles end");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class CreateUserDto {
@Email
private String email;

@ApiModelProperty(value = "${swagger.dashboard.user.model.role}")
String role;

@ApiModelProperty(value = "${swagger.dashboard.user.model.productRoles}", required = true)
@JsonProperty(required = true)
@NotEmpty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package it.pagopa.selfcare.dashboard.web.model.mapper;

import it.pagopa.selfcare.dashboard.connector.exception.InvalidRequestException;
import it.pagopa.selfcare.dashboard.connector.model.user.*;
import it.pagopa.selfcare.dashboard.web.model.UpdateUserDto;
import it.pagopa.selfcare.dashboard.web.model.user.CertifiedFieldResource;
import it.pagopa.selfcare.dashboard.web.model.user.UserResource;
import it.pagopa.selfcare.onboarding.common.PartyRole;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

import javax.validation.ValidationException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -53,5 +58,18 @@ default Map<String, WorkContact> getEmail(UpdateUserDto userDto, String institut
return Map.of();
}

@Mapping(target = "role", expression = "java(retrievePartyRole(user.getRole()))")
UserToCreate toUserToCreate(it.pagopa.selfcare.dashboard.web.model.CreateUserDto user);

@Named("retrievePartyRole")
default PartyRole retrievePartyRole(String role) {
try {
if (StringUtils.isNotBlank(role)) {
return PartyRole.valueOf(role);
}
return null;
} catch (IllegalArgumentException e) {
throw new ValidationException("Invalid role: " + role + ". Allowed values are: " + Arrays.toString(PartyRole.values()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package it.pagopa.selfcare.dashboard.web.model.user;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotEmpty;
import java.util.Set;

@Data
public class UserProductRoles {

@ApiModelProperty(value = "${swagger.dashboard.user.model.role}")
String role;

@NotEmpty
Set<String> productRoles;
}
2 changes: 1 addition & 1 deletion web/src/main/resources/swagger/swagger_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ swagger.dashboard.user.model.birthDate=User's birth date
swagger.dashboard.user.model.email=User's personal email
swagger.dashboard.user.model.workContacts=User's workcontacts, contains the emails associated to every institution the user is assigned to
swagger.dashboard.user.model.institutionalEmail=User's institutional email
swagger.dashboard.user.model.role=User's role
swagger.dashboard.user.model.role=User's role, available value: [MANAGER, DELEGATE, SUBDELEGATE, OPERATOR, ADMIN_EA]
swagger.dashboard.user.model.fields=Fields to retrieve from pdv when searching for user
swagger.dashboard.products.model.roleInfos=User's role infos in product
swagger.dashboard.user.model.productRoles=User's roles in product
Expand Down
Loading
Loading