diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java index 2a18c1bd..ac6b4829 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java @@ -2,6 +2,8 @@ import io.quarkus.security.Authenticated; import io.smallrye.mutiny.Uni; +import it.pagopa.selfcare.onboarding.common.PartyRole; +import it.pagopa.selfcare.user.constant.OnboardedProductState; import it.pagopa.selfcare.user.controller.response.UserResponse; import it.pagopa.selfcare.user.mapper.UserMapper; import it.pagopa.selfcare.user.service.UserEventService; @@ -9,8 +11,10 @@ import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpStatus; import org.eclipse.microprofile.openapi.annotations.Operation; import java.util.List; @@ -72,5 +76,33 @@ public Uni deleteProducts(@PathParam(value = "userId") String userId, @PathParam(value = "productId") String productId) { return userService.deleteUserInstitutionProduct(userId, institutionId, productId); } + + /** + * The updateUserStatus function updates the status of a user's product. + * + * @param userId String + * @param institutionId String + * @param productId String + * @param role PartyRole + * @param productRole String + * @param status OnboardedProductState + * @return A uni<response> + */ + @Operation(summary = "Update user status with optional filter for institution, product, role and productRole") + @PUT + @Path(value = "/{id}/status") + @Produces(MediaType.APPLICATION_JSON) + public Uni updateUserStatus(@PathParam(value = "id") String userId, + @QueryParam(value = "institutionId") String institutionId, + @QueryParam(value = "productId") String productId, + @QueryParam(value = "role") PartyRole role, + @QueryParam(value = "productRole") String productRole, + @QueryParam(value = "status") OnboardedProductState status) { + log.debug("updateProductStatus - userId: {}", userId); + return userService.updateUserStatusWithOptionalFilter(userId, institutionId, productId, role, productRole, status) + .map(ignore -> Response + .status(HttpStatus.SC_NO_CONTENT) + .build()); + } } diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java index 3598429f..414e2b6a 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java @@ -25,4 +25,6 @@ public interface UserInstitutionService { Uni retrieveFirstFilteredUserInstitution(Map queryParameter); Uni deleteUserInstitutionProduct(String userId, String institutionId, String productId); + + Uni updateUserStatusWithOptionalFilterByInstitutionAndProduct(String userId, String institutionId, String productId, PartyRole role, String productRole, OnboardedProductState status); } diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java index 42adbeec..31e7a840 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java @@ -3,6 +3,7 @@ import io.quarkus.mongodb.panache.reactive.ReactivePanacheQuery; import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; +import it.pagopa.selfcare.onboarding.common.PartyRole; import it.pagopa.selfcare.user.constant.OnboardedProductState; import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse; import it.pagopa.selfcare.user.entity.OnboardedProduct; @@ -76,6 +77,14 @@ public Uni deleteUserInstitutionProduct(String userId, String institutionI return updateUserStatusDao(filterMap, OnboardedProductState.DELETED); } + @Override + public Uni updateUserStatusWithOptionalFilterByInstitutionAndProduct(String userId, String institutionId, String productId, PartyRole role, String productRole, OnboardedProductState status) { + Map onboardedProductFilterMap = OnboardedProductFilter.builder().productId(productId).role(role).productRole(productRole).build().constructMap(); + Map userInstitutionFilterMap = UserInstitutionFilter.builder().userId(userId).institutionId(institutionId).build().constructMap(); + Map filterMap = userUtils.retrieveMapForFilter(onboardedProductFilterMap, userInstitutionFilterMap); + return updateUserStatusDao(filterMap, status); + } + @Override public Multi findAllWithFilter(Map queryParameter) { Document query = queryUtils.buildQueryDocument(queryParameter, USER_INSTITUTION_COLLECTION); diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java index 73eb4e2f..114b4e98 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java @@ -8,20 +8,16 @@ import it.pagopa.selfcare.user.controller.response.UserProductResponse; import org.openapi.quarkus.user_registry_json.model.UserResource; -import io.smallrye.mutiny.Uni; import java.util.List; + public interface UserService { Uni> getUsersEmails(String institutionId, String productId); Multi getUserProductsByInstitution(String institutionId); Uni retrievePerson(String userId, String productId, String institutionId); - Multi findAllUserInstitutions(String institutionId, - String userId, - List roles, - List states, - List products, - List productRoles); - + Uni updateUserStatusWithOptionalFilter(String userId, String institutionId, String productId, PartyRole role, String productRole, OnboardedProductState status); + Multi findAllUserInstitutions(String institutionId, String userId, List roles, List states, List products, List productRoles); Uni deleteUserInstitutionProduct(String userId, String institutionId, String productId); + } diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java index cda61ec6..759639d4 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java @@ -2,52 +2,76 @@ import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Uni; +import it.pagopa.selfcare.onboarding.common.PartyRole; import it.pagopa.selfcare.user.constant.OnboardedProductState; import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse; import it.pagopa.selfcare.user.controller.response.UserProductResponse; import it.pagopa.selfcare.user.entity.UserInstitution; import it.pagopa.selfcare.user.entity.filter.OnboardedProductFilter; import it.pagopa.selfcare.user.entity.filter.UserInstitutionFilter; +import it.pagopa.selfcare.user.exception.InvalidRequestException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; import it.pagopa.selfcare.user.mapper.OnboardedProductMapper; import it.pagopa.selfcare.user.mapper.UserInstitutionMapper; +import it.pagopa.selfcare.user.util.UserUtils; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpStatus; import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.jboss.resteasy.reactive.client.api.WebClientApplicationException; import org.openapi.quarkus.user_registry_json.api.UserApi; import org.openapi.quarkus.user_registry_json.model.UserResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.*; -import static it.pagopa.selfcare.user.constant.CustomError.USER_NOT_FOUND_ERROR; -import static it.pagopa.selfcare.user.constant.CustomError.USER_TO_UPDATE_NOT_FOUND; -import static it.pagopa.selfcare.user.util.GeneralUtils.formatQueryParameterList; +import static it.pagopa.selfcare.user.constant.CustomError.*; @RequiredArgsConstructor @ApplicationScoped +@Slf4j public class UserServiceImpl implements UserService { @RestClient @Inject private UserApi userRegistryApi; + private final OnboardedProductMapper onboardedProductMapper; - private final UserInstitutionMapper userInstitutionMapper; + private final UserUtils userUtils; private final UserInstitutionService userInstitutionService; - private static final String USERS_WORKS_FIELD_LIST = "fiscalCode,familyName,email,name,workContacts"; + private final UserInstitutionMapper userInstitutionMapper; + private static final String WORK_CONTACTS = "workContacts"; - private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class); + + private static final String USERS_WORKS_FIELD_LIST = "fiscalCode,familyName,email,name,workContacts"; + + + /** + * The updateUserStatus function updates the status of a user's onboarded product. + */ + @Override + public Uni updateUserStatusWithOptionalFilter(String userId, String institutionId, String productId, PartyRole role, String productRole, OnboardedProductState status) { + + if (status == null) { + return Uni.createFrom().failure(new InvalidRequestException(STATUS_IS_MANDATORY.getMessage())); + } + + userUtils.checkProductRole(productId, role, productRole); + + return userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct(userId, institutionId, productId, role, productRole, status) + .onItem().transformToUni(aLong -> { + if (aLong < 1) { + return Uni.createFrom().failure(new ResourceNotFoundException(USER_TO_UPDATE_NOT_FOUND.getMessage())); + } + return Uni.createFrom().nullItem(); + }); + } @Override public Uni> getUsersEmails(String institutionId, String productId) { - var userInstitutionFilters = constructUserInstitutionFilterMap(institutionId); - var productFilters = constructOnboardedProductFilterMap(productId); - Multi userInstitutions = userInstitutionService.findAllWithFilter(retrieveMapForFilter(userInstitutionFilters, productFilters)); + var userInstitutionFilters = UserInstitutionFilter.builder().institutionId(institutionId).build().constructMap(); + var productFilters = OnboardedProductFilter.builder().productId(productId).build().constructMap(); + Multi userInstitutions = userInstitutionService.findAllWithFilter(userUtils.retrieveMapForFilter(userInstitutionFilters, productFilters)); return userInstitutions.onItem() .transformToUni(obj -> userRegistryApi.findByIdUsingGET(WORK_CONTACTS, obj.getUserId())) .merge() @@ -61,7 +85,7 @@ public Uni> getUsersEmails(String institutionId, String productId) @Override public Multi getUserProductsByInstitution(String institutionId) { - Multi userInstitutions = UserInstitution.find("institutionId", institutionId).stream(); + Multi userInstitutions = UserInstitution.find(UserInstitution.Fields.institutionId.name(), institutionId).stream(); return userInstitutions.onItem() .transformToUni(userInstitution -> userRegistryApi.findByIdUsingGET(USERS_WORKS_FIELD_LIST, userInstitution.getUserId()) .map(userResource -> UserProductResponse.builder() @@ -76,26 +100,23 @@ public Multi getUserProductsByInstitution(String institutio @Override public Uni retrievePerson(String userId, String productId, String institutionId) { - Map queryParameter = buildQueryParams(userId, productId, institutionId); + var userInstitutionFilters = UserInstitutionFilter.builder().userId(userId).institutionId(institutionId).build().constructMap(); + var productFilters = OnboardedProductFilter.builder().productId(productId).build().constructMap(); + Map queryParameter = userUtils.retrieveMapForFilter(userInstitutionFilters, productFilters); return userInstitutionService.retrieveFirstFilteredUserInstitution(queryParameter) .onItem().ifNull().failWith(() -> { log.error(String.format(USER_NOT_FOUND_ERROR.getMessage(), userId)); return new ResourceNotFoundException(String.format(USER_NOT_FOUND_ERROR.getMessage(), userId), USER_NOT_FOUND_ERROR.getCode()); }) .onItem().transformToUni(userInstitution -> userRegistryApi.findByIdUsingGET(USERS_WORKS_FIELD_LIST, userInstitution.getUserId())) - .onFailure(this::checkIfNotFoundException).transform(t -> new ResourceNotFoundException(String.format(USER_NOT_FOUND_ERROR.getMessage(), userId), USER_NOT_FOUND_ERROR.getCode())); + .onFailure(UserUtils::checkIfNotFoundException).transform(t -> new ResourceNotFoundException(String.format(USER_NOT_FOUND_ERROR.getMessage(), userId), USER_NOT_FOUND_ERROR.getCode())); } @Override - public Multi findAllUserInstitutions(String institutionId, - String userId, - List roles, - List states, - List products, - List productRoles) { - var userInstitutionFilters = constructUserInstitutionFilterMap(institutionId, userId); - var productFilters = constructOnboardedProductFilterMap(products, states, roles, productRoles); - Multi userInstitutions = userInstitutionService.findAllWithFilter(retrieveMapForFilter(userInstitutionFilters, productFilters)); + public Multi findAllUserInstitutions(String institutionId, String userId, List roles, List states, List products, List productRoles) { + var userInstitutionFilters = UserInstitutionFilter.builder().userId(userId).institutionId(institutionId).build().constructMap(); + var productFilters = OnboardedProductFilter.builder().productId(products).status(states).role(roles).productRole(productRoles).build().constructMap(); + Multi userInstitutions = userInstitutionService.findAllWithFilter(userUtils.retrieveMapForFilter(userInstitutionFilters, productFilters)); return userInstitutions.onItem().transform(userInstitutionMapper::toResponse); } @@ -110,69 +131,4 @@ public Uni deleteUserInstitutionProduct(String userId, String institutionI }); } - private Map buildQueryParams(String userId, String productId, String institutionId) { - OnboardedProductFilter onboardedProductFilter = OnboardedProductFilter.builder() - .productId(productId) - .build(); - - UserInstitutionFilter userInstitutionFilter = UserInstitutionFilter.builder() - .userId(userId) - .institutionId(institutionId) - .build(); - - Map filterMap = userInstitutionFilter.constructMap(); - filterMap.putAll(onboardedProductFilter.constructMap()); - return filterMap; - } - - private Map constructUserInstitutionFilterMap(String institutionId, String userId) { - return UserInstitutionFilter - .builder() - .institutionId(institutionId) - .userId(userId) - .build() - .constructMap(); - } - - private Map constructOnboardedProductFilterMap(List products, - List states, - List roles, - List productRoles) { - return OnboardedProductFilter.builder() - .productId(formatQueryParameterList(products)) - .role(formatQueryParameterList(roles)) - .status(formatQueryParameterList(states)) - .productRole(formatQueryParameterList(productRoles)) - .build() - .constructMap(); - } - - private Map constructUserInstitutionFilterMap(String institutionId) { - return UserInstitutionFilter - .builder() - .institutionId(institutionId) - .build() - .constructMap(); - } - - private Map constructOnboardedProductFilterMap(String productId) { - return OnboardedProductFilter.builder() - .productId(productId) - .build() - .constructMap(); - } - - private Map retrieveMapForFilter(Map ... maps) { - Map map = new HashMap<>(); - Arrays.stream(maps).forEach(map::putAll); - return map; - } - - private boolean checkIfNotFoundException(Throwable throwable) { - if(throwable instanceof WebClientApplicationException wex) { - return wex.getResponse().getStatus() == HttpStatus.SC_NOT_FOUND; - } - - return false; - } } diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java index 93b22c68..09cb3ec7 100644 --- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java +++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java @@ -1,8 +1,20 @@ package it.pagopa.selfcare.user.util; +import io.smallrye.mutiny.Uni; +import it.pagopa.selfcare.onboarding.common.PartyRole; +import it.pagopa.selfcare.product.entity.ProductRole; +import it.pagopa.selfcare.product.service.ProductService; +import it.pagopa.selfcare.user.exception.InvalidRequestException; import jakarta.enterprise.context.ApplicationScoped; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpStatus; +import org.gradle.internal.impldep.org.apache.commons.lang.StringUtils; +import org.jboss.resteasy.reactive.client.api.WebClientApplicationException; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.Arrays; import java.util.HashMap; @@ -13,10 +25,30 @@ @Slf4j public class UserUtils { + private final ProductService productService; + @SafeVarargs public final Map retrieveMapForFilter(Map... maps) { Map map = new HashMap<>(); Arrays.stream(maps).forEach(map::putAll); return map; } + + public void checkProductRole(String productId, PartyRole role, String productRole) { + if(StringUtils.isNotBlank(productRole) && StringUtils.isNotBlank(productId)) { + try { + productService.validateProductRole(productId, productRole, role); + }catch (IllegalArgumentException e){ + throw new InvalidRequestException(e.getMessage()); + } + } + } + + public static boolean checkIfNotFoundException(Throwable throwable) { + if(throwable instanceof WebClientApplicationException wex) { + return wex.getResponse().getStatus() == HttpStatus.SC_NOT_FOUND; + } + + return false; + } } \ No newline at end of file diff --git a/apps/user-ms/src/main/resources/application.properties b/apps/user-ms/src/main/resources/application.properties index 8045a3d4..e33fa38c 100644 --- a/apps/user-ms/src/main/resources/application.properties +++ b/apps/user-ms/src/main/resources/application.properties @@ -49,5 +49,5 @@ quarkus.rest-client."org.openapi.quarkus.user_registry_json.api.UserApi".url=${U ## AZURE STORAGE ## ## Jacoco -quarkus.jacoco.includes=it/pagopa/selfcare/user/controller/*,it/pagopa/selfcare/user/service/**,it/pagopa/selfcare/user/repository/** +quarkus.jacoco.includes=it/pagopa/selfcare/user/controller/*,it/pagopa/selfcare/user/service/**,it/pagopa/selfcare/user/util/** quarkus.jacoco.data-file=target/jacoco.exec \ No newline at end of file diff --git a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java index cc148bbf..d4690436 100644 --- a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java @@ -6,6 +6,7 @@ import io.quarkus.test.security.TestSecurity; import io.restassured.http.ContentType; import io.smallrye.mutiny.Uni; +import it.pagopa.selfcare.user.constant.OnboardedProductState; import it.pagopa.selfcare.user.exception.InvalidRequestException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; import it.pagopa.selfcare.user.service.UserService; @@ -26,7 +27,7 @@ @QuarkusTest @TestHTTPEndpoint(UserController.class) -public class UserControllerTest { +class UserControllerTest { @InjectMock private UserService userService; @@ -135,6 +136,42 @@ void testGetUserInfoFails() { .statusCode(404); } + @Test + @TestSecurity(user = "userJwt") + void updateUserStatus() { + + Mockito.when(userService.updateUserStatusWithOptionalFilter("userId", null, "prod-pagopa", null, null, OnboardedProductState.ACTIVE)) + .thenReturn(Uni.createFrom().nullItem()); + + given() + .when() + .contentType(ContentType.JSON) + .pathParam("id", "userId") + .queryParam("productId", "prod-pagopa") + .queryParam("status", OnboardedProductState.ACTIVE) + .put("/{id}/status") + .then() + .statusCode(204); + } + + @Test + @TestSecurity(user = "userJwt") + void updateUserStatusError() { + + Mockito.when(userService.updateUserStatusWithOptionalFilter("userId", null, "prod-pagopa", null, null, OnboardedProductState.ACTIVE)) + .thenThrow(new ResourceNotFoundException("user non trovato")); + + given() + .when() + .contentType(ContentType.JSON) + .pathParam("id", "userId") + .queryParam("productId", "prod-pagopa") + .queryParam("status", OnboardedProductState.ACTIVE) + .put("/{id}/status") + .then() + .statusCode(404); + } + /** * Method under test: * {@link UserController#deleteProducts(String, String, String)} diff --git a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInfoServiceTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserInfoServiceTest.java similarity index 100% rename from apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInfoServiceTest.java rename to apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserInfoServiceTest.java diff --git a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserInstitutionServiceTest.java similarity index 82% rename from apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java rename to apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserInstitutionServiceTest.java index 53b0a13e..34ce78bb 100644 --- a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserInstitutionServiceTest.java @@ -134,6 +134,35 @@ void findAllWithFilter() { assertEquals(1, actual.size()); } + @Test + void updateUserStatusWithInstitutionAndOnboardedFilter() { + final String userId = "userId"; + String institutionId = "institutionId"; + String productId = "productId"; + PanacheMock.mock(UserInstitution.class); + ReactivePanacheUpdate update = Mockito.mock(ReactivePanacheUpdate.class); + when(UserInstitution.update(any(Document.class))) + .thenReturn(update); + when(update.where(any())).thenReturn(Uni.createFrom().item(1L)); + UniAssertSubscriber subscriber = userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct(userId, institutionId, productId, null, null, OnboardedProductState.ACTIVE) + .subscribe().withSubscriber(UniAssertSubscriber.create()); + subscriber.assertCompleted().assertItem(1L); + } + + @Test + void updateUserStatusWithInstitutionFilter() { + final String userId = "userId"; + String institutionId = "institutionId"; + PanacheMock.mock(UserInstitution.class); + ReactivePanacheUpdate update = Mockito.mock(ReactivePanacheUpdate.class); + when(UserInstitution.update(any(Document.class))) + .thenReturn(update); + when(update.where(any())).thenReturn(Uni.createFrom().item(1L)); + UniAssertSubscriber subscriber = userInstitutionService.updateUserStatusWithOptionalFilterByInstitutionAndProduct(userId, institutionId, null, null, null, OnboardedProductState.ACTIVE) + .subscribe().withSubscriber(UniAssertSubscriber.create()); + subscriber.assertCompleted().assertItem(1L); + } + @Test void deleteUserInstitutionProduct(){ final String userId = "userId"; diff --git a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java similarity index 78% rename from apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java rename to apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java index b9f162d4..fb351d14 100644 --- a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/service/UserServiceTest.java @@ -12,12 +12,15 @@ import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.helpers.test.AssertSubscriber; import io.smallrye.mutiny.helpers.test.UniAssertSubscriber; -import io.smallrye.mutiny.subscription.UniSubscriber; +import it.pagopa.selfcare.onboarding.common.PartyRole; +import it.pagopa.selfcare.user.constant.OnboardedProductState; import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse; import it.pagopa.selfcare.user.controller.response.UserProductResponse; import it.pagopa.selfcare.user.entity.OnboardedProduct; import it.pagopa.selfcare.user.entity.UserInstitution; +import it.pagopa.selfcare.user.exception.InvalidRequestException; import it.pagopa.selfcare.user.exception.ResourceNotFoundException; +import it.pagopa.selfcare.user.util.UserUtils; import jakarta.inject.Inject; import org.apache.http.HttpStatus; import org.bson.types.ObjectId; @@ -36,11 +39,12 @@ import java.util.Map; import java.util.UUID; +import static it.pagopa.selfcare.user.constant.CustomError.STATUS_IS_MANDATORY; import static it.pagopa.selfcare.user.constant.CustomError.USER_TO_UPDATE_NOT_FOUND; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @QuarkusTest @@ -57,6 +61,9 @@ class UserServiceTest { @InjectMock private UserApi userRegistryApi; + @InjectMock + private UserUtils userUtils; + private static UserResource userResource; private static UserInstitution userInstitution; @@ -167,6 +174,44 @@ void testRetrievePersonFailsWhenPdvFails() { subscriber.assertFailedWith(ResourceNotFoundException.class); } + @Test + void updateUserStatusWithOptionalFilter(){ + doNothing().when(userUtils).checkProductRole("prod-pagopa", PartyRole.MANAGER, null); + when(userInstitutionService + .updateUserStatusWithOptionalFilterByInstitutionAndProduct("userId", "institutionId", "prod-pagopa", PartyRole.MANAGER, null, OnboardedProductState.ACTIVE)).thenReturn(Uni.createFrom().item(1L)); + + UniAssertSubscriber subscriber = userService + .updateUserStatusWithOptionalFilter("userId", "institutionId", "prod-pagopa", PartyRole.MANAGER, null, OnboardedProductState.ACTIVE) + .subscribe() + .withSubscriber(UniAssertSubscriber.create()); + + subscriber.assertCompleted(); + } + + @Test + void updateUserStatusWithOptionalFilterUserNotFound(){ + doNothing().when(userUtils).checkProductRole("prod-pagopa", PartyRole.MANAGER, null); + when(userInstitutionService + .updateUserStatusWithOptionalFilterByInstitutionAndProduct("userId", "institutionId", "prod-pagopa", PartyRole.MANAGER, null, OnboardedProductState.ACTIVE)).thenReturn(Uni.createFrom().item(0L)); + + UniAssertSubscriber subscriber = userService + .updateUserStatusWithOptionalFilter("userId", "institutionId", "prod-pagopa", PartyRole.MANAGER, null, OnboardedProductState.ACTIVE) + .subscribe() + .withSubscriber(UniAssertSubscriber.create()); + + subscriber.assertFailedWith(ResourceNotFoundException.class, USER_TO_UPDATE_NOT_FOUND.getMessage()); + } + + @Test + void updateUserStatusWithOptionalFilterInvalidRequest(){ + UniAssertSubscriber subscriber = userService + .updateUserStatusWithOptionalFilter("userId", "institutionId", null, PartyRole.MANAGER, null, null) + .subscribe() + .withSubscriber(UniAssertSubscriber.create()); + + subscriber.assertFailedWith(InvalidRequestException.class, STATUS_IS_MANDATORY.getMessage()); + } + @Test void retrieveUsersTest() { when(userInstitutionService.findAllWithFilter(any())).thenReturn(Multi.createFrom().item(userInstitution)); diff --git a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/util/UserUtilTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/util/UserUtilTest.java new file mode 100644 index 00000000..547082bc --- /dev/null +++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/util/UserUtilTest.java @@ -0,0 +1,85 @@ +package it.pagopa.selfcare.user.util; + +import io.quarkus.test.InjectMock; +import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.mutiny.helpers.test.UniAssertSubscriber; +import it.pagopa.selfcare.onboarding.common.PartyRole; +import it.pagopa.selfcare.product.entity.Product; +import it.pagopa.selfcare.product.entity.ProductRole; +import it.pagopa.selfcare.product.entity.ProductRoleInfo; +import it.pagopa.selfcare.product.service.ProductService; +import it.pagopa.selfcare.user.exception.InvalidRequestException; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@QuarkusTest +class UserUtilTest { + + @Inject + private UserUtils userUtils; + + @InjectMock + private ProductService productService; + + @Test + void checkRoleValid(){ + when(productService.validateProductRole(any(), any(), any())).thenReturn(new ProductRole()); + Assertions.assertDoesNotThrow(() -> userUtils.checkProductRole("prod-pagopa", PartyRole.MANAGER, "operatore")); + } + + @Test + void checkRoleProductRoleNotFound(){ + when(productService.validateProductRole(any(), any(), any())).thenThrow(new IllegalArgumentException("RoleMappings map for product prod-pagopa not found")); + Assertions.assertThrows(InvalidRequestException.class, () ->userUtils + .checkProductRole("prod-pagopa", PartyRole.MANAGER, "amministratore"), "RoleMappings map for product prod-pagopa not found"); + } + + @Test + void checkRoleProductRoleListNotExists(){ + when(productService.validateProductRole(any(), any(), any())).thenThrow(new IllegalArgumentException("Role DELEGATE not found")); + Assertions.assertThrows(InvalidRequestException.class, () -> userUtils + .checkProductRole("prod-pagopa", PartyRole.DELEGATE, "operatore"), "Role DELEGATE not found"); + } + + @Test + void checkProductRoleWithoutProductRole(){ + when(productService.validateProductRole(any(), any(), any())).thenThrow(new IllegalArgumentException("ProductRole operatore not found for role MANAGER")); + Assertions.assertThrows(InvalidRequestException.class, () -> userUtils + .checkProductRole("prod-io", PartyRole.MANAGER, "operatore"), "ProductRole operatore not found for role MANAGER"); + } + + @Test + void checkProductRoleWithoutRole(){ + when(productService.validateProductRole(any(), any(), any())).thenThrow(new IllegalArgumentException("Role is mandatory to check productRole")); + Assertions.assertThrows(InvalidRequestException.class, () -> userUtils + .checkProductRole("prod-io", null, "operatore"), "Role is mandatory to check productRole"); + } + + @Test + void checkRoleWithoutProduct(){ + when(productService.validateProductRole(any(), any(), any())).thenThrow(new IllegalArgumentException("ProductRole admin not found for role MANAGER")); + Assertions.assertThrows(InvalidRequestException.class, () -> userUtils + .checkProductRole("prod-io", PartyRole.MANAGER, "admin"), "ProductRole admin not found for role MANAGER"); + } + + private Product getProductResource() { + Product productResource = new Product(); + Map map = new HashMap<>(); + ProductRoleInfo productRoleInfo = new ProductRoleInfo(); + ProductRole productRole = new ProductRole(); + productRole.setCode("operatore"); + productRoleInfo.setRoles(List.of(productRole)); + map.put(PartyRole.MANAGER, productRoleInfo); + productResource.setRoleMappings(map); + return productResource; + } + +}